【问题标题】:Bash parameter expansion can't match spaces in variables like $* and $@Bash 参数扩展无法匹配 $* 和 $@ 等变量中的空格
【发布时间】:2019-03-09 06:42:09
【问题描述】:

使用破折号 (0.5.10.2),我可以这样做:

% dash
$ set -- x hello world
$ echo "<${*#x }>"
<hello world>

这是我所期望的行为。 $* 的内容(由set 分配并由空格分隔的x hello world)通过shell parameter expansion 运行以删除任何前导 以进行回声,从而产生hello world,我' m 与周围的括号相呼应,以表明缺少周围的空白。

我无法在 bash (5.0.2(1)-release) 中复制它。看来空格,一个分隔符,是不可访问的:

% bash
$ set -- x hello world
$ echo "<${*#x }>"
<x hello world>
$ echo "<${@#x }>"     # trying $@ instead of $*
<x hello world>
$ echo "<${*#x}>"      # without the space works but now I have a space
< hello world>
$ echo "<${*#x?}>"     # trying the `?` wildcard for a single character
<x hello world>
$ echo "<${*#x\ }>"    # trying to escape the space
<x hello world>
$ echo "<${*/#x /}>"   # using bash pattern substitution instead
<x hello world>
$ echo "<${*#x$IFS}>"  # trying the input field separator variable
<x hello world>

这里有解决办法吗?或许可以通过某种方式修改$* 或更改输出字段分隔符?

我目前的解决方法是将它分配给一个临时变量,但这很难看。 (我需要 bash,否则我会坚持使用 /bin/sh,即 dash。)

【问题讨论】:

  • 当我读到pubs.opengroup.org/onlinepubs/9699919799/utilities/…如果参数是#*@,扩展的结果是未指定的。 -- 所以两者同样正确,并且想要在所有 POSIX 平台上工作的脚本不应该依赖任何一种行为。 (var=$*${var// /&lt;SPACE&gt;},你已经准备好了)。
  • @CharlesDuffy - Err... 嗯.. 不是${var// /&lt;SPACE&gt;} 带有子字符串替换的参数扩展 .. bashism? POSIX 仅在我阅读时提供 suffixprefix 删除。
  • @DavidC.Rankin,非常正确。尽管如此,var=$* 避免依赖未定义行为的观点仍然成立。
  • @DavidC.Rankin – 这是一个 bash 问题,所以 bashism 没问题......虽然我使用 var="$*"; echo "${var#x }" 达到同样的效果,因为我很少在 bash 中编写脚本,我试图限制我的 bash 脚本的 bashisms 到了绝对必要的地方。
  • 同意,我只是对您明显使用 dash 感到困惑。

标签: bash shell parameter-expansion


【解决方案1】:

对于类似数组的操作数,对每个元素应用字符串操作它们以空格连接。因此,您不能将它们应用于加入空间。

下面是一个例子:

$ set -- hello world "hello world with spaces"
$ echo "${*// /<SPACE>}"
hello world hello<SPACE>world<SPACE>with<SPACE>spaces

每个参数中的空格都可以很好地替换,但$* 插入的空格不受影响。

解决方法确实是一个临时变量。

【讨论】:

  • 啊,很好的演示。 echo "&lt;${*#hello }&gt;"(使用你的 set 行)更适合我正在做的事情,果然它给了我&lt;hello world world with spaces&gt;,因为你提到的隐含 for each
  • 如果您真正的问题是“如何连接除第一个参数之外的所有参数?”那么答案是"${*:2}"
  • 实际上,是的:这是对我(过于简单化)问题的字面回答,尽管我认为您的第一段和 Charles Duffy 对该问题的评论结合起来可以获得更多信息。 (另外,我有一大堆条件,比如[ "$*" != "${*#* foo* bar}" ],我必须将它们转换为case 模式,比如( *\ foo*\ bar* ),但这并没有成为我在这里提出的简化问题。)
猜你喜欢
  • 2017-01-27
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多