LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Read and write to a co-process in bash (https://www.linuxquestions.org/questions/linux-software-2/read-and-write-to-a-co-process-in-bash-685772/)

Bambi535 11-24-2008 12:28 PM

Read and write to a co-process in bash
 
Hello all,
Ksh provides the option to read from a co-process by means of:
Code:

#!/bin/ksh
find . -name "*.log" |&
while read -p; do
# whatever
 :
done

How can this be done in bash?
Using a pipeline is no option for me as I set some shell variables inside the while loop that I need to access later on.

Thanks,
Opher.

i92guboj 11-24-2008 01:41 PM

It depends. The evident way is to use a file to hold the data, and read it back from the loop.

You can take the whole list into the loop with <<<, like this
Code:

IFS=' '
n=1
while read line
do
  echo "${line}"
  n=$((n+1))
done <<< $(find .)
echo $n

IFS is the internal field separator marker. <<< will import the whole list into the loop. $n is there so you can check that the var is accessible after while is over.

Bambi535 11-24-2008 05:42 PM

Thanks for the reply,
Quote:

Originally Posted by i92guboj (Post 3353030)
It depends. The evident way is to use a file to hold the data, and read it back from the loop.

Indeed, but then I have to clean up temporary files.
Also, I'm not sure how this behaves if I background (&) the first command and in my script read faster than the command generates output ...?
Quote:

You can take the whole list into the loop with <<<, like this
Code:

IFS=' '
n=1
while read line
do
  echo "${line}"
  n=$((n+1))
done <<< $(find .)
echo $n

IFS is the internal field separator marker. <<< will import the whole list into the loop. $n is there so you can check that the var is accessible after while is over.
I'm afraid I was not specific enough. In my script I have several loops and commands reading from the co-process output. So I would need to brace ({ ... }) the bulk of my script. Also the natural order of things is lost
Code:

{
while read; do
# first loop
 :
done
read
...
while read; do
# second loop
 :
done
} < <(find .)


Bambi535 11-25-2008 12:58 PM

Some more research (google -> bash FAQ) revealed that co-processes are not supported directly.
Instead, one can use a named pipe pair (one for input and one for output).
There are two options: 1) place the extra code in your script.
2) source the functions/coproc.bash (from the 3.2 distribution)
ex.
Code:

  local fifo="/var/tmp/getoptions.$$.$RANDOM"
  mkfifo $fifo || {
    echo "$(basename $0): getoptions: Error creating named pipe. Exiting." >&2
    exit 2
  }
  ( find . >$fifo ; rm -f $fifo ) &
  trap 'echo Received SIGPIPE >&2' SIGPIPE
  globalvar=
  while read; do
  # first loop
    :
  done <$fifo
  # do something with globalvar
  while read; do
  #second loop
    :
  done <$fifo
  trap - SIGPIPE



All times are GMT -5. The time now is 06:14 PM.