时间:2019-12-15 21:03:17

标签: shell sh posix

我用我能找到的所有shell运行了以下命令(*shsh实现的名称);尽管我希望所有人都能打印match,但结果却不一致。我不知道哪种行为是正确和可靠的。

*sh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'

使用dash from Ubuntu bionic's repo(和灰;这是短划线的符号链接)

$ dash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用bash 4.4.20(1)-发行版(x86_64-pc-linux-gnu)和5.0.11(1)-发行版(arm-unknown-linux-androideabi)

$ bash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用ksh版本AJM 93u + 2012-08-01和版本JM 93t + 2010-03-05(已随SunOS omniosce 5.11预先安装)

$ ksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用ksh @(#)PD KSH v5.2.14 99.07.13.2(OpenBSD 6.6和its Linux port上的默认shell)

$ ksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$

使用lksh @(#)LEGACY KSH R56 2018/01/14,mksh @(#)MIRBSD KSH R56 2018/01/14(在Ubuntu bionic上这些是不同的二进制文件)和mksh @(#)MIRBSD KSH R57 2019/03/01

$ lksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ mksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

最高为0.13.1

$ posh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

使用yash 2.46

$ yash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

并使用zsh 5.4.2(x86_64-ubuntu-linux-gnu)和5.7.1(arm-unknown-linux-androideabi);模拟sh

$ zsh -c 'emulate sh; case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

我迷失在POSIX's Shell Command Language specification 中;尚无法找到我的问题的简单答案:应如何以全局模式解释由变量扩展产生的转义反斜杠?是\\还是\还是未指定?


Case Conditional Construct下显示:

  

按照从case语句的开始到结尾的顺序,每个标记化合物列表的 pattern 均应进行波浪号扩展,参数扩展,命令替换和算术扩展,并且根据{{​​3}}(还描述了引用部分模式的效果的描述),将这些扩展的结果与单词的扩展进行比较。

请注意,这并不是说模式会被删除引号;但是在模式匹配表示法下,它表示:

  

<反斜杠>字符应转义以下字符。转义的应该被丢弃

但是并不清楚当模式是扩展结果时是否仍然会发生这种情况。

1 个答案:

答案 0 :(得分:2)

也许此参考资料可以解决您的问题。子句在POSIX's Shell Command Language specification - under Pattern Matching Notation中指出,

  

2.13.1 匹配单个字符的模式

     

<backslash>字符应转义以下字符。转义的<backslash>将被丢弃。如果某个模式以未转义的<backslash>结尾,则不确定该模式是否不匹配任何内容,或者该模式被视为无效

上述规则适用于使用case语句和使用==结构在bash中使用test全局匹配运算符的模式。

因此,由于您的$2在进行模式匹配时保持无引号,因此f\\oo的字面值将永远丢失并被解释为f\oo

为了清理起见,shell在引用删除期间保留了您的字面值,并且仅当在此模式匹配规则中应用传递的参数时,这种行为才会表现出来。