Append to a pipe and pass on?
Solution 1
In the simplest of the options, this does append to the pipe stream:
$ echo "750/12.5" | { bc; echo "/24"; }
60
/24
However that has an unexpected newline, to avoid that you need to either use tr:
$ echo "750/12.5" | { bc | tr -d '\n' ; echo "/24"; }
60/24
Or, given the fact that a command expansion removes trailing newlines:
$ printf '%s' $( echo "750/12.5" | bc ); echo "/24"
60/24
But probably, the correct way should be similar to:
$ echo "$(echo "750/12.5" | bc )/24"
60/24
Which, to be used in bc, could be written as this:
$ bc <<<"$(bc <<<"750/12.5")/24"
2
Which, to get a reasonable floating number precision should be something like:
$ bc <<<"scale=10;$(bc <<<"scale=5;750/12.5")/24"
2.5000000000
Note the need of two scale, as there are two instances of bc.
Of course, one instance of bc needs only one scale:
$ bc <<<"scale=5;750/12.5/24"
In fact, what you should be thinking about is in terms of an string:
$ a=$(echo "750/12.5") # capture first string.
$ echo "$a/24" | bc # extend the string
2
The comment about scale from above is still valid here.
Solution 2
I achieved this using sed
and replacing the end of the line:
echo "my text" | sed 's/$/ more text/'
Returns:
my text more text
Your example:
echo "750/12.5" | bc | sed 's/$/\/24/' | bc
Solution 3
Alternative approach:
TL;DR: Use cat
to concatenate with stdin (-
) as an argument. Note that it'll newline-separate your concatenated streams; remove if undesired.
Unfortunately this approach is a bit cumbersome for your particular use case since bc
fails if there's a newline in the middle of that expression:
$ echo "750/12.5" | bc | cat - <(echo "/24") | bc
60
(standard_in) 2: parse error
You can work around that by deleting the newline from the original bc
result:
$ echo "750/12.5" | bc | tr -d '\n' | cat - <(echo "/24") | bc
2
However, I came upon this question by googling "bash append to pipe", and in my case I actually do want that newline between the concatenations. So for those here for the same reason, use | cat - <(...)
:
$ echo foo | cat - <(echo bar)
foo
bar
$ echo foo | cat - <(echo bar) | sort | cat - <(echo last_line)
bar
foo
last_line
$ echo foo | cat - <(echo bar) | sort | cat <(echo header) - <(echo last_line)
header
bar
foo
last_line
Solution 4
Something like this seems to work using xargs:
$ echo "750/12.5" | bc |xargs -I{} echo "{}+20" |bc
80
Or even:
$ echo "750/12.5" | bc |echo "$(</dev/stdin)+20" |bc
80
And why not :
$ bc <<<20+$(bc <<<"750/12.5")
80
Related videos on Youtube
Philip Kirkbride
Updated on September 18, 2022Comments
-
Philip Kirkbride almost 2 years
I have a simple bash function dividing two numbers:
echo "750/12.5" | bc
I'd like to take the output from
bc
and append/24
and pipe said result to another instance ofbc
.Something like:
echo "750/12.5" | bc | echo $1 + "/24" | bc
Where
$1
is the piped result.P.S. I realize I could just do
echo "750/12.5/24" | bc
my question is more in regards to the appending of text to a pipe result. -
Gilles 'SO- stop being evil' about 7 yearsSimple??? Why not a simple command substitution?
-
Gilles 'SO- stop being evil' about 7 yearsWhy not? Because it's unnecessarily complicated. Use a command substitution.
-
done about 7 years@Gilles A
{…}
is simple. The answer walks toward showing the user a "command substitution" as the best solution. Read again. -
Keith Ripley over 4 yearsThis doesn't work for multiline text input. In my case, I wanted to append an extra line to multiline text and process it. Ended up using: (figlet my_text && echo "new line") | boxes