1

I'm having trouble with an unfortunate mis-feature in bash, illustrated by this function:

trying ()
{
    res=0;
    echo $res;
    cat some_text_file | while read op rpt rec; do
        res=1;
        echo $res;
    done;
    echo $res
}

What i had expected was that the last echo $res would print 1 - however, it prints 0. The reason is that the loop starting with cat some_text_file | while read op rpt rec; do runs in a sub-shell, whereas in ksh it doesn't.

A work-around for this simple case would be:

trying ()
{
    res=0;
    echo $res;
    while read op rpt rec; do
        res=1;
        echo $res;
    done < some_text_file;
    echo $res
}

However, in most cases it would be more like cat some_file | awk '{...}' | while read ..., and I'd really like to not create a temporary file just for this; it just ought to work.

Unfortunately I have work with bash on my servers, otherwise it would be ksh everywhere. So, are there any good ways around this?

1 Answer 1

2

There are a few workarounds:

  1. You can activate shopt -s lastpipe to get the ksh-like behavior. This only works where job control is disabled ��� i.e. you can always use this option in standalone scripts, but while using an interactive shell it will only affect pipes inside (subshells).

  2. If the variables only need to be short-lived (and there isn't anything besides the 'while' loop which would need to read stdin), you can pipe to a command list:

    cat some_file | awk '{...}' | {
        res=0
        echo $res
        while read op rpt rec; do
            res=1
            echo $res
        done
        echo $res
    }
    
  3. You can use bash's process substitution operator <(...) to read from a subshell as if it were a named file, including redirecting it to a 'while' loop:

    res=0
    echo $res
    while read op rpt rec; do
        res=1
        echo $res
    done < <(cat some_file | awk '{...}')
    echo $res
    
  4. You're already using awk...

    cat some_file | awk '{...}' | awk '
       BEGIN { res = 0 }
       { res = 1 }
       END { print res }
    '
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .