Bash 参数扩展

发布于 2024-10-14 13:04:24 字数 1467 浏览 2 评论 0原文

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

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

按原样工作正常。但是,在阅读 Shell 参数扩展 部分时根据 bash 手册,这似乎应该能够通过一个步骤完成。但是,我不太清楚如何做到这一点。

我已经尝试过:

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

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

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

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

如果可能的话,我希望看到执行这个看似两步过程的逻辑,没有 if/else 结构,但仅使用 Shell 参数扩展功能

谢谢。


Elderarthis 的编辑

脚本的其余部分只是:

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

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

我知道 TIMTOWTDI; 我正在寻找是否可以仅使用 Shell 参数扩展部分中的内容来完成:-)


编辑< /strong> 对于 Mikel:

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

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

I have a script which uses the following logic:

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

This works fine, as-is. However, in reading the Shell Parameter Expansion section of the bash manual, it seems this should be able to be done in a single step. However, I can't quite wrap my head around how to do it.

I've tried:

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

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

and a few ways of nesting them, but nesting seems to be disallowed as far as I can tell.

I realize I've already got a working solution, but now I'm genuinely curious if this is possible. It's something that would be straightforward with a ternary operator, but I don't think bash has one.

If this is possible, I'd like to see the logic to do this seeming two-step process, with no if/else constructs, but using only any combination of the Shell Parameter Expansion features.

Thank you.


EDIT for elderarthis:

The remainder of the script is just:

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

I just want ACTION=echo as a sanity check against myself, hence, passing any argument will actually do the deletion (by nullifying ${ACTION}, whereas passing no args leaves echo in there.

And I know TIMTOWTDI; I'm looking to see if it can be done with just the stuff in the Shell Parameter Expansion section :-)


EDIT for Mikel:

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

The last needs to have ACTION='', and thus return a blank line/null value.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伏妖词 2024-10-21 13:04:24

如果我坚持用少于 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
$ 

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


如果子 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 未设置或为空

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

If I insisted on doing it in fewer than 4 lines and no sub-shell, then I think I'd use:

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

This cheats slightly - it creates a blank action rather than an empty action if there is an argument to the script. If there is no argument, then ACTION is empty before the second line. On the second line, if action is empty, set it to 'echo'. In the expansion, since you (correctly) do not quote $ACTION, no argument will be passed for the blank.

Tester (xx.sh):

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

echo $ACTION rm -f a b c

Tests:

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

If the last line is incorrect, then remove the colon from before the plus.


If a sub-shell is acceptable, then one of these two single lines works:

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

The first corresponds to the first version shown above (empty first arguments are treated as absent); the second deals with empty arguments as present. You could write:

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

to make the relation with the second clearer - except you're only going to use one or the other, not both.


Since the markdown notation in my comment confused the system (or I got it wrong but didn't get to fix it quickly enough), my last comment (slightly amended) should read:

The notation ${var:+' '} means 'if $var is set and is not empty, then use what follows the +' (which, in this case, is a single blank). The notation ${var+' '} means 'if $var is set - regardless of whether it is empty or not - then use what follows the +'. These other expansions are similar:

  • ${var:=X} - set $var to X unless it already has a non-empty value.
  • ${var:-X} - expands to $var if it has a non-empty value and expands to X if $var is unset or is empty

Dropping the colon removes the 'empty' part of the test.

拔了角的鹿 2024-10-21 13:04:24
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 传递,它将保留为 echo,但我不认为这是一件坏事。

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

ACTION=${1:-echo}

is correct.

Make sure it's near the top of your script before anything modifies $1 (e.g. before any set command). Also, it wouldn't work inside a function, because $1 would be the first parameter to the function.

Also check if $1 is set but null, in which case fix how you're calling it, or use ACTION=${1-echo} (note there is no :).


Update

Ah, I assumed you must have meant the opposite, because it didn't really make sense otherwise.

It still seems odd, but I guess as a mental exercise, maybe you want something like this:

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

It's not quite right: it gives ACTION=o, but I think something along those lines should work.

Further, if you pass echo as $1, it will stay as echo, but I don't think that's a bad thing.

It's also terribly ugly, but you knew that when asking the question. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文