1

Let's say I have 2 bash commands:

$ A
apple
pear
lemon

A is writing this really fast but waiting 1 minute after "lemon" to terminate successfully.

I want every line being processed as input for B separately and instantly. but I do not want to wait for A to terminate but rather call a new B for every fast appearing line. B would then add something to the output of A let's say:

$ A <for every line appearing> B
1 apple
1 pear
1 banana

How can I do this with bash?

update

here are the original commands:

$sudo alive6 -l eth1 -W 0.2 | sed -e 's/Alive: \(.*\) \[ICMP echo-reply\]/\1%eth0/' -e'/Scanned.*/d' -e'//d'

responds instantly, while

$sudo alive6 -l eth1 -W 0.2 | sed -e 's/Alive: \(.*\) \[ICMP echo-reply\]/\1%eth0/' -e'/Scanned.*/d' -e'//d' | while read l; do echo $l; done

seems to wait for alive6 to finish

1
  • This is a useful thing to keep track of, I'm adding it to my favourites. By the way, I'm guessing you have no way to modify the behaviour of A?
    – icedwater
    Commented Jun 25, 2013 at 10:35

3 Answers 3

1
A | while read -r l; do B &; done

B is run in the background to address the following requirement: line being processed as input for B separately and instantly.

5
  • 1
    If B reads standard input you'll need to use a different file descriptor.
    – l0b0
    Commented Jun 25, 2013 at 10:41
  • Why are you backgrounding B?
    – l0b0
    Commented Jun 25, 2013 at 10:42
  • @l0b0 backgrounding is how I would address the "line being processed as input for B separately and instantly" requirement. Commented Jun 25, 2013 at 10:46
  • "Instantly" is not the same as "asynchrously". This solution will end up shuffling lines with B's execution time.
    – l0b0
    Commented Jun 25, 2013 at 10:50
  • interestingly this does not make it faster. I actually have sed as the B-command. A simple example like ls -l && sleep 3 | sed 's/.*/&/' | while read l; do echo $l; done does work though. Commented Jun 25, 2013 at 11:04
0

Use unbuffer to disable A's line buffering.

$ unbuffer A <for every line appearing> B
2
  • 1
    @icedwater: And bash scripts would only work if bash is installed. Commented Jun 25, 2013 at 10:32
  • 1
    Yes, but it is more likely you will find bash on a system than unbuffer.
    – icedwater
    Commented Jun 25, 2013 at 10:33
0

In Bash:

while read -r -u 9 line || [ -n "$line" ]
do
    B "$line"
done 9< <(A)
  • Works even if A prints backslashes.
  • Works even if the output of A does not end in a newline.
  • Works even if B reads standard input, but not if it for some reason reads file descriptor 9. In that case you'll have to create a pipe with mkfifo.
  • Runs B synchronously, processing the output of A asynchrously.

Not the answer you're looking for? Browse other questions tagged or ask your own question.