参数扩展导致空字符串的处理方式有所不同

时间:2019-10-30 10:36:11

标签: bash

更新

bug-bash mailing list中的某个人有confirmed,这是一个错误。


如果有人感兴趣,可以在the latest commit to devel branch中找到修复程序。


bash -c 'echo "${1##*""}"' _ bar

打印一个空行,

bash -c 'echo "${1##*"${1##*}"}"' _ bar

打印bar

我不明白。 ${1##*}扩展为空字符串,因此应将"${1##*}"视为"",但似乎bash并不这样认为。

在其他流行的sh实现中似乎对此达成共识:

$ sh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ash -c 'echo "${1##*"${1##*}"}"' _ bar

$ dash -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh93 -c 'echo "${1##*"${1##*}"}"' _ bar

$ mksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ posh -c 'echo "${1##*"${1##*}"}"' _ bar

$ yash -c 'echo "${1##*"${1##*}"}"' _ bar

$ zsh -c 'echo "${1##*"${1##*}"}"' _ bar

$

bash(带有或不带有--posix)是唯一不符合此要求的

$ bash -c 'echo "${1##*"${1##*}"}"' _ bar
bar

在没有子字符串处理的情况下,行为符合预期:

$ bash -c 'echo "${1##*"${1+}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar ''

$ 

我真的很想知道是否有对此的解释,我在手册中找不到。这是错误还是对标准的误解?此行为记录在某处吗?


PS:我知道一种快速的解决方法是取消对内部PE的引用,但这不能回答我的问题,并且可能导致包含特殊字符的字符串导致不良结果。

1 个答案:

答案 0 :(得分:2)

  

这不是答案

首先,我认为这是由于特殊的glob-rules,但最终,我认为这是bash中的错误。以下四个示例应该使您了解为什么我认为这是一个错误:

$ bash -c 'echo "${1##*${1%%bar}}"' _ foobar        # case 1
bar
$ bash -c 'echo "${1##*${1%%foobar}}"' _ foobar     # case 2

$ bash -c 'echo "${1##*"${1%%bar}"}"' _ foobar      # case 3
bar
$ bash -c 'echo "${1##*"${1%%foobar}"}"' _ foobar   # case 4
foobar

案例1和案例3的引号不同。但是形式为${parameter##word}的参数扩展使用路径名扩展规则来处理word。因此*foo*"foo"具有相同的行为,因为除非它们包含特殊的模式字符(*?,...),否则可以忽略路径名扩展中的双引号。在以下示例中可以看到:

$ bash -c 'echo "${1##*${2%%b*r}}"' _ 'foobar' 'f*ob*r'
bar
$ bash -c 'echo "${1##*"${2%%b*r}"}"' _ 'foobar' 'f*ob*r'
foobar
  

如果是这种情况,为什么情况2和情况4的行为会有所不同?