bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Aw: Re: echo hi | read a; echo $a # Does not print hi AS WITH pdksh


From: ANDERSSEN, Borge T.
Subject: Aw: Re: echo hi | read a; echo $a # Does not print hi AS WITH pdksh
Date: Fri, 20 Jun 2003 12:01:00 +0200

Hi Chet,


Thanks a lot for your quick and kind answer.  I'm sorry I bothered you.
I should have checked the bash FQA before writing the bug report.
To be honest though, I'm not a frequent user of bash.  I started with
unix long before bash was around and more or less "grew up" with ksh (and sh)
which compared to bash had/have the advantage of being on every unix
system available, but I keep noticing that bash is becoming more and
more common.  And it surely has some nice features that I'm missing in ksh.

Here at Volkswagen (VW) we have until recently only used proprietary
unix systems (AIX, HP-UX, IRIX, OSF1, SunOS, SUPER-UX, Tru64), but are
currently in the process of evaluating Linux as an alternative
(although we have one productive massive parallel supercomputer with
256 Xeon 2.8 GHz CPUs [512 Hyper-Threads] running Linux).

As part of the process evaluating Linux, I was compiling some C programs
with gcc.  My standard method for obtaining the default names a C compiler
adds as -Dname[=...] is:
    [g]cc -v foo.c 2>&1 | defined_names | sort
where 'defined_names' is the following script:

#!/bin/ksh
while read LINE; do
    while  echo "$LINE" | sed -n 's/\(.* \)-D\([^ ]* \)\(.*\)/\2\1\3/p' | read 
NAME LINE;  do
        echo "$NAME"
    done
done

As I tried this on Linux, only newlines appeared. 
When trying to find out why, the man pages for pdksh revealed:
    "
    BTW, the most frequently reported bug is
            echo hi | read a; echo $a   # Does not print hi
    I'm aware of this and there is no need to report it.
    "

which hasn't been fixed in 4 years!!!   :-(     :-C

In despair I tried bash, but got the same result.

After reading the Bash FAQ I now know that bash in this
case (E4) works as designed.  However I don't really grasp the reason
for bash not supporting the way ksh does it.  Unless it is because of
the POSIX.2 shell specification, I assume that it has something to do
with unwanted effects when running the last command of a pipeline in
the context of the parent shell.  Could using Shared Memory be a method
for supporting the way ksh does it?

To be more specific:
1) When a bash shell is created allocate some MBs of Shared Memory.

2) When running a pipeline like   "command | read V1 V2 V3"   behind the scenes 
do:
   "command | read V1 V2 V3; <copy V1, V2 and V3 to Shared Memory>"

3) When the child of the shell running the pipeline exits then in the parent 
shell do:
   a) If there is something in Shared Memory then update the shell variables and
      environment variables accordingly.
   b) Clear the Shared Memory.


The way bash runs the pipeline  "command | read V1 V2"  becomes easier to
handle after "Here Strings" was added.  Although "Here Strings"
obviously has the same shortcoming as "Here Documents" when it comes
to detecting EOF, i.e. isn't detected.

With "Here Strings" 'defined_names' looks like:

#!/bin/bash
while read LINE; do
    while  read NAME LINE <<<"`printf \"$LINE\" | sed -n 's/\(.* \)-D\([^ ]* 
\)\(.*\)/\2\1\3/p'`"; [ -n "$NAME" ];  do
        echo "$NAME"
    done
done

However my favourite alternative is to rewrite
    command | read V1 V2 ... Vn
as
    $(command | { read V1 V2 ... Vn; echo "eval V1='$V1';V2='$V2'; ... 
;Vn='$Vn';((! $?))"; }

The reason is that it works with bash, ksh and pdksh and propagates
the read return status, i.e. detects EOF.

Using this alternative the example used in the bash FAQ section E4 can be 
written as:
$(/usr/local/bin/ipaddr | { IFS=.; read A B C D; echo "eval 
A='$A';B='$B';C='$C';D='$D';((! $?))"; })

and 'defined_names' looks like:

#!/bin/bash
while read LINE; do
    while  $(echo "$LINE" | sed -n 's/\(.* \)-D\([^ ]* \)\(.*\)/\2\1\3/p' | { 
read NAME LINE; echo "eval NAME='$NAME';LINE='$LINE';((! $?))"; });  do
        echo "$NAME"
    done
done

For the completeness, with "Here Documents" 'defined_names' looks like:

#!/bin/bash
while read LINE; do
    while
        read NAME LINE <<- E___O___T
            `echo "$LINE" | sed -n 's/\(.* \)-D\([^ ]* \)\(.*\)/\2\1\3/p'`
        E___O___T
        [ -n "$NAME" ]
    do
        echo "$NAME"
    done
done


Regards,
Børge

======================================================================================

Chet Ramey wrote:
> 
> > Machine Type: i686-pc-linux-gnu
> >
> > Bash Version: 2.05b
> > Patch Level: 0
> > Release Status: release
> >
> > Description:
> >         echo hi | read a; echo $a   # Does not print hi
> 
> Read the Bash FAQ, question E4.
> 
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
> ( ``Discere est Dolere'' -- chet )
> 
> Chet Ramey, ITS, CWRU    chet@po.CWRU.Edu    http://cnswww.cns.cwru.edu/~chet/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]