Command substitution allows us to use the output of a command as an
expansion:
[me@linuxbox ~]$ echo $(ls)Desktop Documents ls-output.txt Music Pictures Public Templates Videos[me@linuxbox ~]$ ls -l $(which cp)-rwxr-xr-x 1 root root 71516 2012-12-05 08:58 /bin/cp
There is an alternative syntax for command substitution in older shell
programs that is also supported in bash . It uses back quotes instead
of the dollar sign and parentheses:
demo() { echo $(pwd) # /a/b/c ( # launch a subshell to run the following cd haha echo $(pwd) # /a/b/c/haha ) echo $(pwd) # /a/b/c}foo() { cd haha}foo_sub() ( # note here we use '(' cd haha)bar() { echo $(pwd) # /a/b/c foo echo $(pwd) # /a/b/c/haha}bar1() { echo $(pwd) # /a/b/c foo_sub # this will launch a subshell echo $(pwd) # /a/b/c, so pwd here will not change}
再来看一个陷进,
#!/bin/bash# Pitfalls of variables in a subshell.outer_variable=outerechoecho "outer_variable = $outer_variable"echo(# Begin subshellecho "outer_variable inside subshell = $outer_variable"inner_variable=inner # Setecho "inner_variable inside subshell = $inner_variable"outer_variable=inner # Will value change globally?echo "outer_variable inside subshell = $outer_variable"# Will 'exporting' make a difference?# export inner_variable# export outer_variable# Try it and see.# End subshell)echoecho "inner_variable outside subshell = $inner_variable" # Unset.echo "outer_variable outside subshell = $outer_variable" # Unchanged.echoexit 0# What happens if you uncomment lines 19 and 20?# Does it make a difference?# Answer by yychi: No! 'export' in subshell does not transfer changes to parent shell.
In general, an external command in a script forks off a subprocess, whereas a Bash builtin does not. For this reason, builtins execute more quickly and use fewer system resources than their external command equivalents.
$ read reply < <(echo haha)# ^ ^ First < is redirection, second is process substitution.$ echo $replyhaha
再来看一个更复杂的例子,
#!/bin/bash# wr-ps.bash: while-read loop with process substitution.# This example contributed by Tomas Pospisek.# (Heavily edited by the ABS Guide author.)echoecho "random input" | while read ido global=3D": Not available outside the loop." # ... because it runs in a subshell.doneecho "\$global (from outside the subprocess) = $global"# $global (from outside the subprocess) =echo; echo "--"; echowhile read ido echo $i global=3D": Available outside the loop." # ... because it does NOT run in a subshell.done < <( echo "random input" )# ^ ^echo "\$global (using process substitution) = $global"# Random input# $global (using process substitution) = 3D: Available outside the loop.echo; echo "##########"; echo# And likewise . . .declare -a inloopindex=0cat $0 | while read linedo inloop[$index]="$line" ((index++)) # It runs in a subshell, so ...doneecho "OUTPUT = "echo ${inloop[*]} # ... nothing echoes.echo; echo "--"; echodeclare -a outloopindex=0while read linedo outloop[$index]="$line" ((index++)) # It does NOT run in a subshell, so ...done < <( cat $0 )echo "OUTPUT = "echo ${outloop[*]} # ... the entire script echoes.exit $?