2

我有一个使用以下逻辑的脚本:

if [ ! -z "$1" ]; then         # if any parameter is supplied
    ACTION=                    # clear $ACTION
else
    ACTION=echo                # otherwise, set it to 'echo'
fi

这工作正常,原样。但是,在阅读手册的Shell Parameter Expansion部分时bash,似乎这应该可以一步完成。但是,我不能完全理解如何做到这一点。

我试过了:

ACTION=${1:-echo}              # ends up with $1 in $ACTION

ACTION=${1:+}
ACTION=${ACTION:-echo}         # ends up always 'echo'

以及一些嵌套它们的方法,但据我所知,嵌套似乎是不允许的。

我意识到我已经有了一个可行的解决方案,但现在我真的很好奇这是否可能。对于三元运算符来说,这很简单,但我认为 bash 没有。

如果这是可能的,我希望看到执行这个看似两步过程的逻辑,没有 if/else 构造,但仅使用Shell Parameter Expansion features的任何组合

谢谢你。


编辑Elderarthis:

脚本的其余部分只是:

find . -name "*\?[NMSD]=[AD]" -exec ${ACTION} rm -f "{}" +

我只是想ACTION=echo对自己进行一次健全性检查,因此,传递任何参数实际上都会删除(通过使 ${ACTION} 无效,而不传递任何参数会在其中留下 echo。

我知道 TIMTOWDI;我正在寻找是否可以仅使用 Shell Parameter Expansion 部分中的内容来完成 :-)


编辑米克尔:

$ cat honk.sh
#!/bin/bash
ACTION=${1-echo}
echo $ACTION
$ ./honk.sh
echo
$ ./honk.sh foo
foo

最后一个需要有ACTION='',因此返回一个空行/空值。

4

2 回答 2

6

如果我坚持用少于 4 行且没有子 shell 来完成,那么我想我会使用:

ACTION=${1:+' '}
: ${ACTION:=echo}

这有点作弊 - 如果脚本有参数,它会创建一个空白动作而不是一个空动作。如果没有参数,则 ACTION 在第二行之前为空。在第二行,如果 action 为空,则将其设置为“echo”。在扩展中,由于您(正确地)没有引用 $ACTION,因此不会为空白传递任何参数。

测试人员(xx.sh):

ACTION=${1:+' '}
: ${ACTION:=echo}

echo $ACTION rm -f a b c

测试:

$ sh xx.sh 1
rm -f a b c
$ sh xx.sh
echo rm -f a b c
$ sh xx.sh ''
echo rm -f a b c
$ 

如果最后一行不正确,则删除加号前的冒号。


如果子外壳是可以接受的,那么这两条单行之一就可以了:

ACTION=$([ -z "$1"     ] && echo echo)
ACTION=$([ -z "${1+X}" ] && echo echo)

第一个对应于上面显示的第一个版本(空的第一个参数被视为不存在);第二个处理当前的空参数。你可以写:

ACTION=$([ -z "${1:+X}" ] && echo echo)

使与第二个的关系更清晰-除非您只使用其中一个,而不是两者。


由于我评论中的降价符号混淆了系统(或者我弄错了但没有足够快地修复它),我的最后一条评论(稍作修改)应该是:

该符号${var:+' '}表示“如果$var已设置且不为空,则使用+' 后面的内容(在这种情况下,它是一个空白)。该符号${var+' '}表示“如果$var已设置 - 无论它是否为空 - 然后使用+' 后面的内容。这些其他扩展是类似的:

  • ${var:=X}- 设置$varX除非它已经有一个非空值。
  • ${var:-X}-$var如果它具有非空值,则扩展为X如果$var未设置或为空,则扩展为

删除冒号会删除测试的“空”部分。

于 2011-01-25T04:46:37.350 回答
2
ACTION=${1:-echo}

是正确的。

$1在进行任何修改之前(例如,在任何set命令之前),确保它位于脚本顶部附近。此外,它在函数内部不起作用,因为$1它将是函数的第一个参数。

还要检查是否$1设置但为空,在这种情况下修复你如何调用它,或者使用ACTION=${1-echo}(注意没有:)。


更新

啊,我认为你的意思一定是相反的,因为否则它没有任何意义。

它仍然看起来很奇怪,但我想作为一种心理锻炼,也许你想要这样的东西:

#!/bin/bash
shopt -s extglob
ACTION=$1
ACTION=${ACTION:-echo}
ACTION=${ACTION/!(echo)/}    # or maybe ACTION=${ACTION#!(echo)}
echo ACTION=$ACTION

这不太正确:它给出了ACTION=o,但我认为这些方面的东西应该有效。

此外,如果您通过echoas $1,它将保持为回声,但我认为这不是一件坏事。

它也非常难看,但你在问这个问题时就知道了。:-)

于 2011-01-25T03:46:21.677 回答