考虑以下简单的shell脚本:
rm -rf bar \"bar\"
mkdir -p bar
touch bar/baz
echo "bar"/*
我用bash,ksh,zsh和dash获得了预期的输出,但我没有得到 它与豪华:
susam@debian:~$ bash foo.sh
bar/baz
susam@debian:~$ ksh foo.sh
bar/baz
susam@debian:~$ zsh foo.sh
bar/baz
susam@debian:~$ dash foo.sh
bar/baz
susam@debian:~$ posh foo.sh
bar/*
我试图了解posh的行为是否符合POSIX标准或是否是错误。
POSIX文档中的相关部分似乎是“2.6 Word扩展”:
他们都提到路径名扩展发生在引用删除之前。
- 除非
set -f
生效,否则应执行路径名扩展(请参阅路径名扩展)。- 引用删除(请参阅引用删除)应始终执行。
醇>
考虑到这一点,豪华行为看起来正确,因为"bar"/*
在引用删除之前并不完全匹配上面的任何路径,因此不会发生路径扩展。
所以这让我怀疑如果有一个名为"bar"
的目录,即引号是目录名的一部分,那么豪华就会匹配它。但是下面改进的脚本表明这不是真的。
rm -rf bar \"bar\"
mkdir -p \"bar\"
touch \"bar\"/baz
echo "bar"/*
这是输出:
susam@debian1:~$ bash foo2.sh
bar/*
susam@debian1:~$ ksh foo2.sh
bar/*
susam@debian1:~$ zsh foo2.sh
foo2.sh:3: no matches found: bar/*
susam@debian1:~$ dash foo2.sh
bar/*
susam@debian1:~$ posh foo2.sh
bar/*
因此,posh中的模式"bar"/*
既不匹配路径bar/baz
也不匹配路径"bar"/baz
。它与之匹配的是什么?豪华行为是错误还是功能?
以下是版本详细信息,以帮助您帮助我:
susam@debian:~$ cat /etc/debian_version
8.3
susam@debian:~$ dpkg -l bash ksh zsh dash posh
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-===========================-==================-==================-============================================================
ii bash 4.3-11+b1 amd64 GNU Bourne Again SHell
ii dash 0.5.7-4+b1 amd64 POSIX-compliant shell
ii ksh 93u+20120801-1 amd64 Real, AT&T version of the Korn shell
ii posh 0.12.3 amd64 Policy-compliant Ordinary SHell
ii zsh 5.0.7-5 amd64 shell with lots of features
答案 0 :(得分:2)
这是posh
中的错误 - 请参阅错误#636601。从posh
版本0.12.6开始,它仍处于打开状态。
附加到该错误的discussion,您会找到patch。应用时,posh
的行为与bash
类似(因此,在您的第一个示例echo "bar"/*
中提供bar/baz
)。
此外, bash
(以及已修补的 posh
)的行为确实符合POSIX 。标准说
- 报价删除(请参阅报价删除)应始终执行。
醇>
这意味着 字面上 ,作为纯语法操作,在最后一步删除保护性引号。正如hek2mgl所指出的,引号的语义含义仍将适用于前面的步骤。 (否则,例如像"*"
这样的引用根本就没有任何效果。)
所以第二个想法,这个结论是不正确的:
考虑到这一点,豪华行为看起来正确,因为" bar" / * 在引用删除之前,字面上不匹配上面的任何路径,所以路径 扩张不会发生。
答案 1 :(得分:0)
即使在quote removal之前,shell也会将不带引号的"
视为字符串分隔符,而不是文字字符。
此外,我无法重现您的测试结果。在这两种情况下,bash和posh给了我相同的结果。
答案 2 :(得分:-2)
您可以尝试使用bash --posix
(以获得POSIX行为),您会看到结果为bar/baz
。
重点是" bar"的路径名扩展。给出bar
。有关模式匹配un truc th name扩展的详细信息,请参阅SCL第2.13节。