Bash参数扩展

时间:2011-01-25 03:21:19

标签: bash shell parameters expansion

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

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

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

我试过了:

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

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

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

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

如果可以,我希望看到这样做的逻辑似乎是两步过程,没有if / else结构,但只使用Shell Parameter Expansion功能的任意组合

谢谢。


elderarthis的

编辑

脚本的其余部分只是:

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

我只想要ACTION=echo作为对自己的理智检查,因此,传递任何参数实际上都会删除(通过使$ {ACTION}无效,而传递没有args会在那里留下回声。

我知道TIMTOWTDI;我想看看它是否只能通过Shell参数扩展部分中的内容来完成: - )


对于Mikel

编辑

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

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

2 个答案:

答案 0 :(得分:6)

如果我坚持用少于4行并且没有子shell,那么我认为我会使用:

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

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

Tester(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
$ 

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


如果子shell是可接受的,则这两条单行中的一条可以工作:

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

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

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

与第二个更清楚的人建立关系 - 除了你只会使用其中一个,而不是两个。


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

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

  • ${var:=X} - 将$var设置为X,除非它已经有非空值。
  • ${var:-X} - 如果其中包含非空值,则展开为$var,如果X未设置或为空,则展开为$var

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

答案 1 :(得分: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,但我认为沿着这些方向应该有用。

此外,如果您将echo作为$1传递,它将保持为回声,但我认为这不是一件坏事。

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