Re: return from function doesn't work when used in tail of pipeline
On Thu, Aug 12, 2010 at 01:23:20PM +1000, Martin Schwenke wrote: > Description: > I don't believe that the following behaviour is sensible or > matches the standard/documentation: > > $ f () { { echo 1 ; echo 2 ; } | while read line ; do echo $line ; > return 0 ; done ; echo foo ; return 1 ; } > $ f > 1 > foo > $ echo $? > 1 > > I expect f to return 0 from within the loop because a function > is executing. > > I know the return 0 is in a subprocess at the end of a > pipeline... but that whole pipeline is running within a > function. You already know the reason it behaves the way it does, so I'm not quite sure what answer you expect to receive. It's not a bug -- it's the normal behavior of every shell. imadev:~$ sh -c 'f() { (return 0); return 1; }; f; echo $?' 1 imadev:~$ ksh -c 'f() { (return 0); return 1; }; f; echo $?' 1 imadev:~$ bash -c 'f() { (return 0); return 1; }; f; echo $?' 1 A return that's run in a subshell doesn't cause the parent shell to return. > In > general I expect to be able to pipe the output of a command > into a loop and have the loop read lines until some condition > occurs, at which point my function returns. Ah, a real question! :) Use a process substitution in bash: f() { while IFS= read -r somevar; do [[ $somevar = *quit* ]] && return 0 printf '%s\n' "$somevar" done < <(grep foo bar) return 1 } > This could > obviously be done using a out=$(cmd) subprocess... except in > the case where cmd can block before producing all of its > output. Hence, the above seems convenient. The process substitution doesn't require cmd to finish before it starts producing data. It's equivalent to a pipeline, except that the reader doesn't need to be in a subshell.
Re: read -d'' -n1
> On Thu, Aug 12, 2010 at 1:46 PM, Jan Schampera wrote: > >> while read -d'' -n1 ch; do On Thu, Aug 12, 2010 at 01:50:34PM +0800, Sharuzzaman Ahmat Raslan wrote: > Which part is the mistake, and what is the solution? If you want the argument of -d to be an empty string, you have to separate the empty string argument from the -d with some whitespace: read -d '' -n1 ch Otherwise, -d'' is exactly the same as -d (the '' goes away entirely), and read tries to use the -n1 as the argument of -d. Since -d only takes a single character, the - becomes the delimiter.
Re: Wrong prompt and incorrect parsing if completion is used
On 8/9/10 12:02 PM, Egmont Koblinger wrote: > Hello, > > I've found a weird behavior. In some circumstances, if I use TAB completion > during typing a command line, the final command is parsed differently than > if I typed it all along. > > I'm on Ubuntu Lucid. The bug described below occurs only if I use the > bash-completion package (that is, I source /etc/bash_completion - it can be > found at http://packages.ubuntu.com/lucid/bash-completion ). However, the > behavior suggests that probably it's a bug in bash itself, not the > bash-completion package. Maybe. Before I take a closer look at this, what does running the offending set of commands with `set -x' enabled show? Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
PIPESTATUS always returns only a single element
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc -I/usr/src/packages/BUILD/bash-4.1 -L/usr/src/packages/BUILD/bash-4.1/../readline-6.1 Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' -DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -std=gnu89 -Wuninitialized -Wextra -Wno-unprototyped-calls -Wno-switch-enum -Wno-unused-variable -Wno-unused-parameter -ftree-loop-linear -pipe -fprofile-use uname output: Linux russte14 2.6.31.12-0.2-desktop #1 SMP PREEMPT 2010-03-16 21:25:39 +0100 x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-suse-linux-gnu Bash Version: 4.1 Patch Level: 7 Release Status: release Description: PIPESTATUS never shows more than 1 array element after executing a multiple command pipe Repeat-By: Execute the following script: #!/bin/bash # # A script to test PIPESTATUS and pipefail # echo " cmd: set +o pipefail" echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null" set +o pipefail ps -ef 2>&1 | grep "^$USR" >/dev/null echo "expect: PIPESTATUS = 1 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} \$? = $?" echo echo " cmd: set -o pipefail" echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null" set -o pipefail ps -ef 2>&1 | grep "^$USR" >/dev/null echo "expect: PIPESTATUS = 1 0 \$? = 1; got: PIPESTATUS = ${PIPESTATUS[*]} \$? = $?" echo echo " pipe: ps aux 2>&1 | grep "^\$USER" >/dev/null" ps aux 2>&1 | grep "^$USER" >/dev/null echo "expect: PIPESTATUS = 0 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} \$? = $?" echo "expect: PIPESTATUS = 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} \$? = $?" # # End of script None of the 'got' results 'expect'ing multiple PIPESTATUS results work.
Re: return from function doesn't work when used in tail of pipeline
On Thu, 12 Aug 2010 08:16:21 -0400, Greg Wooledge wrote: > You already know the reason it behaves the way it does, so I'm not > quite sure what answer you expect to receive. It's not a bug -- it's > the normal behavior of every shell. > > imadev:~$ sh -c 'f() { (return 0); return 1; }; f; echo $?' > 1 > [...] > A return that's run in a subshell doesn't cause the parent shell to > return. I want it to either obey the principle of least surprise or be more clearly documented! return is syntax so I expect it to do what its documentation says it does... I've been programming in shell for 20 years and this one surprised me. I have a very strong Unix background and I clearly understand things like not being able to set variables in subshells. It also surprised other people, with similar backgrounds, who I showed it to. It is much less obvious than many other shell subtleties. There are some obvious exceptions to the strict Unix subprocess model in shell programming (e.g. I can set a variable without exporting it and see it in a subshell) and I expected this to be one of them. Adding something like this to the documentation for return would probably be enough: Note that many compound commands that might be used in a function cause subshells to be created. In this subshells return will behave as though it is being used outside a function. > Use a process substitution in bash: > > f() { > while IFS= read -r somevar; do > [[ $somevar = *quit* ]] && return 0 > printf '%s\n' "$somevar" > done < <(grep foo bar) > return 1 > } [...] > The process substitution doesn't require cmd to finish before it > starts producing data. It's equivalent to a pipeline, except that > the reader doesn't need to be in a subshell. Thanks, I'll use that unless I can come up with something more portable! :-) peace & happiness, martin
Re: PIPESTATUS always returns only a single element
On 8/12/10 6:37 PM, lstee...@gmail.com wrote: > Bash Version: 4.1 > Patch Level: 7 > Release Status: release > > Description: > PIPESTATUS never shows more than 1 array element after executing a > multiple command pipe > > Repeat-By: > Execute the following script: > > #!/bin/bash > # > # A script to test PIPESTATUS and pipefail > # > echo " cmd: set +o pipefail" > echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null" > set +o pipefail > ps -ef 2>&1 | grep "^$USR" >/dev/null > echo "expect: PIPESTATUS = 1 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} > \$? = $?" > echo > echo " cmd: set -o pipefail" > echo " pipe: ps -ef 2>&1 | grep "^\$USR" >/dev/null" > set -o pipefail > ps -ef 2>&1 | grep "^$USR" >/dev/null > echo "expect: PIPESTATUS = 1 0 \$? = 1; got: PIPESTATUS = ${PIPESTATUS[*]} > \$? = $?" > echo > echo " pipe: ps aux 2>&1 | grep "^\$USER" >/dev/null" > ps aux 2>&1 | grep "^$USER" >/dev/null > echo "expect: PIPESTATUS = 0 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} > \$? = $?" > echo "expect: PIPESTATUS = 0 \$? = 0; got: PIPESTATUS = ${PIPESTATUS[*]} \$? > = $?" > # > # End of script > > None of the 'got' results 'expect'ing multiple PIPESTATUS results work. Interesting. I can't reproduce it. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/