views:

121

answers:

6

I am getting a stream of numbers in a pipe, and would like to perform some operations before passing them on to the next section, but I'm a little lost about how I would go about it without breaking the pipe.

for example

> echo "1 2 3 4 5" | some command | cat 
1 4 9 16 25
>

Would you have any ideas on how to make something like this work? The actual operation I want to perform is simply adding one to every number.

+4  A: 
echo 1 2 3 4 5|(
  read line; 
  for i in $line;
  do
    echo -n "$((i * i)) "; 
  done; 
  echo
)

The () creates a subshell. You could instead create a script for that.

Matthew Flaschen
Thanks Matthew! Exactly what I was looking for. In retrospect, I should have been able to figure this out on my own though :-p
brice
A: 

If you prefer Python:

#!/bin/python
num = input()
while num:
    print(int(num) + 1) # Whatever manipulation you want
    try:
        num = input()
    except EOFError:
        break
Amber
+1  A: 

Or..

echo "1 2 3 4 5" | xargs -n 1 | while read number 
 do
   echo $((number * number))
 done
lasseoe
Thanks lasseoe. To put it in the middle of the pipe, I'd need to put it in a subshell too. Yours doesn't drop numbers though, which is better!
brice
Actually, any shell commands in a pipe are automatically run in a subshell; the only reason to put this in `()` would be to group it with a final `echo` as Matthew Flaschen did, and even there you could just as well use `{}` (which do grouping without forcing a subshell).
Gordon Davisson
A: 

Or you can pipe to expression to bc:

echo "1 2 3 4 5" | (
  read line; 
  for i in $line;
  do
    echo $i^2 | bc; 
  done; 
  echo
)
DiggyF
+3  A: 

We can think of it as a "map" (functional programming). There are a lot of ways of writing a "map" function in bash (using stdin, function args, ...), for example:

map_stdin() {
  local FUNCTION=$1
  while read LINE; do
    $FUNCTION $LINE
  done
}

square() {
  echo "$(($1 * $1))"
}

$ echo "1 2 3 4 5" | xargs -n1 | map_stdin square | xargs
1 4 9 16 25
tokland
A: 
echo 1 2 3 4 5 | xargs -n 1 bash -c 'echo $(($1*$1))' args 
tilo