仅获取上一个命令的倒数第二个参数

仅获取上一个命令的倒数第二个参数
[ -f /root/.bash_aliases ] || echo "$_"

给我]

我想/root/.bash_aliases

我也尝试过

[ -f /root/.bash_aliases ] || echo !:2

但它给了我以下结果

[ -f /root/.bash_aliases ] || echo /root/.bash_aliases
/root/.bash_aliases

我只想/root/.bash_aliases

答案1

这就是函数的用途:

print_if_not_regular() {
  [ -f "$1" ] || printf '%s\n' "$1"
}
print_if_not_regular /root/.bash_aliases

有些 shell 喜欢eszsh具有匿名函数:

(){[ -f "$1" ] || printf '%s\n' $1} /root/.bash_aliases # zsh
@ {[ -f $1 ] || printf '%s\n' $1} /root/.bash_aliases # es

我会避免使用$_.例如,如果您有 DEBUG 陷阱,它就不再起作用。

$ bash -c 'trap ": \"\$((cmdcount+=1))\"" DEBUG; echo foo; echo "$_"'
foo
2

请注意,这!:n不是最后一个命令的第 n 个参数,而是前一个命令行的第 n词汇标记(存储到历史记录中的最后一行(甚至可能是多行))。例如,在

echo $(echo A B)
echo foo; echo !:1

!:1不会扩展为foo(最后一个命令的最后一个参数),也不会扩展为 (上一个命令行的命令B的最后一个参数),而是。在这里您需要输入:echoecho$(echo A B)

[ -f /root/.bash_aliases ] ||
  echo !:2

也就是说,将其输入在单独的行中。在这里,即使当您输入第二行时历史记录行尚未完全完成,它也恰好(偶然)起作用。同样的技巧在(t)csh(历史扩展的来源)中不起作用,也不起作用zsh

答案2

使用

test -f /root/.bash_aliases || echo "$_"

或者

test -f /root/.bash_aliases || printf '%s\n' "$_"

$_将扩展到上一个命令的最后一个参数。在您的示例中,前一个命令是[,它的最后一个参数是]

上面的最后一个命令是test,它的最后一个参数是文件名。

test[是相同的命令,但[需要 a]作为其最后一个命令行参数。在这种情况下,这就是很难使用它$_来获取文件名的原因。

上述解决方案的优点是至少可以在bash(除非您DEBUG设置了陷阱)和中工作zsh


如果你的文件名在一个变量中,那么这样做就很简单了

[ -f "$name" ] || printf '%s\n' "$name"

或者

if [ ! -f "$name" ]; then
    printf '%s\n' "$name"
fi

取决于您对if语句和短路逻辑测试的偏好。

相关内容