Sus*_*Pal 11 linux shell debian posix
考虑以下简单的shell脚本:
rm -rf bar \"bar\"
mkdir -p bar
touch bar/baz
echo "bar"/*
Run Code Online (Sandbox Code Playgroud)
我用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/*
Run Code Online (Sandbox Code Playgroud)
我试图了解posh的行为是否符合POSIX标准或是否是一个bug.
POSIX文档中的相关部分似乎是"2.6 Word扩展":
他们都提到路径名扩展发生在引用删除之前.
- 除非有效,否则应执行路径名扩展(请参阅路径名扩展)
set -f.- 报价删除(参见报价删除)应始终执行.
考虑到这一点,豪华行为看起来正确,因为"bar"/*在删除引用之前不会与上面的任何路径字面匹配,因此不会发生路径扩展.
所以这让我怀疑如果有一个字面命名的目录"bar",即引号是目录名称的一部分,那么豪华就会匹配它.但是以下改进的脚本表明这不是真的.
rm -rf bar \"bar\"
mkdir -p \"bar\"
touch \"bar\"/baz
echo "bar"/*
Run Code Online (Sandbox Code Playgroud)
这是输出:
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/*
Run Code Online (Sandbox Code Playgroud)
因此"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
Run Code Online (Sandbox Code Playgroud)
这是一个错误posh- 请参阅错误#636601。从 0.12.6 版本开始它仍然开放posh。
在对该错误的讨论的附件中,您将找到一个补丁。应用时,其posh行为类似于bash(因此在第一个示例中echo "bar"/*给出bar/baz)。
bash此外, (和patched posh )的行为确实符合 POSIX。标准说
- 报价删除(请参阅报价删除)应始终最后执行。
从字面上看,这是一个纯粹的语法操作,用于在最后一步中删除保护性引号。正如 hek2mgl 所指出的,引号的语义仍然适用于前面的步骤。(否则,例如像这样的引用"*"根本不会产生任何效果。)
所以转念一想,这个结论并不正确:
考虑到这一点,优雅的行为看起来是正确的,因为“bar”/*在删除引号之前并不与上面的任何路径字面匹配,因此不会发生路径扩展。