Brian Chrisman
Brian Chrisman

Reputation: 3684

bash: evaluating stdin while outputting to stdout unaltered

In bash, I want to be able to analyze stdin more or less 'out of band', while copying to stdout without moving it through tmp files, variables, or explicitly named fifos.

Two similar examples:

while read foo; do somefunc $foo; echo "$foo"; done

tee >(grep -qs bar && do_something_but_i_am_trapped_in_a_process_substitution_shell)

line-by-line wouldn't be the end of the world, but I'd prefer something cleaner.

What I'd like to be able to do is something with: exec, file descriptor redirections, and tee, such that I can do something like:

hasABar=$(grep -qs bar <file descriptor magic> && echo yes || echo no)

... then do something based on whether I have a 'bar', but in the end, stdout is still a copy of stdin.

UPDATE: from Kugelman's answer below, I adapted to the following, which both work.

(
    exec 3>&1
    myVar=$(tee /dev/fd/3 | grep -qs bar && echo yes || echo no) 
    #myVar=$(grep -qs bar <(tee /dev/fd/3) && echo yes || echo no)
    echo "$myVar" > /tmp/out1
)

Upvotes: 3

Views: 117

Answers (1)

John Kugelman
John Kugelman

Reputation: 361585

You could dup stdout to fd 3 and then use tee to write to both stdout and fd 3 simultaneously.

exec 3>&1
tee /dev/fd/3 | grep -qs bar

Here's an example of that in action. I bolded the lines I typed.

$ cat test
#!/bin/bash
exec 3>&1
tee /dev/fd/3 | grep bar >&2

$ ./test | wc
foo
bar
bar
foo
^D
      3       3      12

See how both grep bar and wc processed my input? grep found the string "bar" when I typed it, and wc counted everything I typed.

Upvotes: 2

Related Questions