Dea*_*nny 4 bash shell-script command-substitution subshell variable
我写了一个简单的脚本
#!/bin/bash -x
selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
echo $ts
Run Code Online (Sandbox Code Playgroud)
但 $ts 什么也没显示。如何显示 $ts 变量,或者如何从变量中的命令获取退出状态代码?
selentry=`ls -l / | sort`
Run Code Online (Sandbox Code Playgroud)
在:
selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
Run Code Online (Sandbox Code Playgroud)
与更现代的相同:
selentry=$(ls -l / | sort ; ts=${PIPESTATUS[0]})
Run Code Online (Sandbox Code Playgroud)
里面的代码在$(...)
子shell环境中运行(在bash
和 以外的shell的情况下ksh93
,它甚至在不同的shell进程中运行)。因此,对该子shell 中的变量所做的任何修改都不会影响父shell。
当你这样做时:
var=$(cmd)
Run Code Online (Sandbox Code Playgroud)
但是 的退出状态cmd
在 中可用$?
。$PIPESTATUS
在以下情况下,这不会扩展到:
var=$(foo | bar)
Run Code Online (Sandbox Code Playgroud)
只包含一个值(子shell的退出代码,这里将是退出状态bar
(除非pipefail
选项打开,在这种情况下它可能是foo
非零的退出状态)。数组zsh
所在的位置更糟$pipestatus
不受赋值命令的影响。
但是,在这里,如果您不关心sort
(子shell)的退出状态,则可以执行以下操作:
selentry=$(ls -l / | sort; exit "${PIPESTATUS[0]}")
ts=$?
Run Code Online (Sandbox Code Playgroud)
在这里,您还可以执行以下操作:
exec 3< <(ls -l /) # here ls is started as an asynchronous command
ls_pid=$!
selentry=$(sort <&3)
sort_status=$?
wait "$ls_pid"
exec 3<&- # close that fd 3
ls_status=$?
Run Code Online (Sandbox Code Playgroud)
甚至:
{
selentry=$(sort)
sort_status=$?
wait "$!"
ls_status=$?
} < <(ls -l /)
Run Code Online (Sandbox Code Playgroud)
关于让变量赋值在命令替换中存活的更普遍的问题,在 中ksh93
,您可以使用${ cmd;}
命令替换的形式(ksh93
虽然不支持$PIPESTATUS
/ $pipestatus
)。
var=${
foo; c1=$?
bar; c2=$?
}
Run Code Online (Sandbox Code Playgroud)
在其他类似 Bourne 的 shell 中没有等效项,您需要通过其他方式(例如临时文件)传递数据:
var=$(
foo; echo "c1=$?" > "$tempfile"
bar; echo "c2=$?" >> "$tempfile"
)
. "$tempfile"
Run Code Online (Sandbox Code Playgroud)
或者在这里:
selentry=$(
ls -l / | sort
typeset -p PIPESTATUS | sed '1s/PIPESTATUS/my_&/' > "$tempfile"
}
. "$tempfile"
ls_status=${my_PIPESTATUS[0]}
Run Code Online (Sandbox Code Playgroud)