我运行了以下命令(*sh
是一个名字sh
实现)以及我能找到的所有 shell;虽然我期待所有的打印match
,我得到了不一致的结果。我不知道哪种行为是正确的、可靠的。
*sh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
With 来自 Ubuntu Bionic 仓库的 dash https://packages.ubuntu.com/bionic/dash(和 ash;这是破折号的符号链接)
$ dash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match
使用 bash 4.4.20(1)-release (x86_64-pc-linux-gnu) 和 5.0.11(1)-release (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(预装 SunOSomniosce 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 上的默认 shell,以及它的Linux端口 https://github.com/dimkr/loksh/)
$ 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'
$
与雅什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
And I'm lost in POSIX's Shell Command Language specification https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18†; couldn't find a straightforward answer to my question yet: How should an escaped backslash resulting from a variable expansion be interpreted in a glob pattern? As \\
or as \
? Or is it unspecified?
† Under Case Conditional Construct https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_04_05 it says:
按照从 case 语句的开头到结尾的顺序,每个pattern标记复合列表的标签应进行波形符扩展、参数扩展、命令替换和算术扩展,并且这些扩展的结果应根据中描述的规则与单词的扩展进行比较模式匹配表示法 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 (它还描述了引用模式部分的效果)
请注意,它并没有说模式会被引用删除;而是说模式会被删除。但在模式匹配表示法下,它说:
字符应转义后面的字符。转义的 将被丢弃
但它并没有澄清当该模式是扩展的结果时是否仍然会发生这种情况。
对于任何感兴趣的人来说,该标准对此并不清楚;不过他们会在新版本中修改它。以下是 POSIX 错误报告的一些链接,其中广泛讨论了该问题。
- 0001234:在大多数 shell 中,反斜杠在模式匹配方面没有两个含义 https://www.austingroupbugs.net/view.php?id=1234
- 0001190:反斜杠在 shell 中有两种特殊含义,在括号表达式中只丢失其中之一 https://www.austingroupbugs.net/view.php?id=1190
- 0000985:case 语句模式和替代扩展中缺少引号删除 https://www.austingroupbugs.net/view.php?id=985