我写了一个简单的脚本
#!/bin/bash -x
selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
echo $ts
但 $ts 什么也没显示。如何显示 $ts 变量,或者如何从变量中的命令获取退出状态代码?
selentry=`ls -l / | sort`
答案1
在:
selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
与更现代的相同:
selentry=$(ls -l / | sort ; ts=${PIPESTATUS[0]})
中的代码在子 shell 环境中运行(在和 shell 以外的$(...)
情况下,它甚至在不同的 shell 进程中运行)。因此,对该子 shell 中的变量进行的任何修改都不会影响父 shell。bash
ksh93
当你这样做时:
var=$(cmd)
然而 的退出状态cmd
在 中可用$?
。这并不适用于$PIPESTATUS
以下情况:
var=$(foo | bar)
仅包含一个值(子shell的退出代码,这里将是退出状态bar
(除非该选项打开,在这种情况下,如果它非零,则pipefail
可能是退出状态)。数组所在的位置更糟不受赋值命令影响。foo
zsh
$pipestatus
不过,在这里,如果您不关心sort
(子 shell 的)退出状态,您可以这样做:
selentry=$(ls -l / | sort; exit "${PIPESTATUS[0]}")
ts=$?
在这里,你还可以这样做:
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=$?
甚至:
{
selentry=$(sort)
sort_status=$?
wait "$!"
ls_status=$?
} < <(ls -l /)
关于让变量赋值在命令替换中继续存在的更普遍的问题,在 中ksh93
,您可以使用${ cmd;}
命令替换的形式(但ksh93
不支持$PIPESTATUS
/ $pipestatus
)。
var=${
foo; c1=$?
bar; c2=$?
}
在其他类似 Bourne 的 shell 中没有类似的功能,您需要通过其他方式(例如临时文件)传递数据:
var=$(
foo; echo "c1=$?" > "$tempfile"
bar; echo "c2=$?" >> "$tempfile"
)
. "$tempfile"
或者在这里:
selentry=$(
ls -l / | sort
typeset -p PIPESTATUS | sed '1s/PIPESTATUS/my_&/' > "$tempfile"
}
. "$tempfile"
ls_status=${my_PIPESTATUS[0]}