根据 bash 手册,如果extglob
启用,则模式@(pattern-list)
应匹配pattern-list
(以 分隔|
)中的任何模式。在这里它按预期工作:
$ shopt -s extglob
$ ls -ld /@(.|usr)/@(.|local)/@(.|share)/
drwxr-xr-x 50 root root 4096 Sep 2 16:39 /./././
drwxr-xr-x 12 root root 4096 Oct 15 2018 /usr/././
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/./
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/share/
drwxr-xr-x 725 root root 20480 Sep 2 16:42 /usr/./share/
Run Code Online (Sandbox Code Playgroud)
但是如果我们在三个模式列表中的每一个中交换替代品,大部分应该匹配的目录都消失了:
$ ls -ld /@(usr|.)/@(local|.)/@(share|.)/
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/share/
Run Code Online (Sandbox Code Playgroud)
与不存在的子目录相同。在这里它有效:
$ ls -ld /@(.|usr)/@(.|foo)/@(.|share)/
drwxr-xr-x 50 root root 4096 Sep 2 16:39 /./././
drwxr-xr-x 12 root root 4096 Oct 15 2018 /usr/././
drwxr-xr-x 725 root root 20480 Sep 2 16:42 /usr/./share/
Run Code Online (Sandbox Code Playgroud)
在这里它没有:
$ ls -ld /@(usr|.)/@(foo|.)/@(share|.)/
ls: cannot access '/@(usr|.)/@(foo|.)/@(share|.)/': No such file or directory
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?这种行为是在某处记录的,还是只是简单的错误?(这是 GNU bash,版本 4.4.12(1)。)
在 bash-4.3 之前,“.” 术语永远不会匹配。来自 bash(1),v5.0,路径名扩展部分:
Run Code Online (Sandbox Code Playgroud)When a pattern is used for pathname expansion, the character ``.'' at the start of a name or immediately following a slash must be matched explicitly, unless the shell option dotglob is set. The filenames ``.'' and ``..'' must always be matched explicitly, even if dotglob is set.
这里对行为的描述有点模糊,但并不意味着“。” 必须位于每个(子)模式的开头,您可以通过以下方式证明:
$ echo /@(usr|.)/@(local|.)/@(share|.)/
/usr/local/share/
$ echo /@(usr|..)/@(local|..)/@(share|..)/
/../../../ /usr/../../ /usr/local/../ /usr/local/share/
Run Code Online (Sandbox Code Playgroud)
所以问题是特定于“.”的。并不是 ”..”。
我相信这是 中的一个错误extglob_skipname()
,从循环中的第 218 行开始while (t = glob_patscan (pp, pe, '|')) { ... }
,这种模式中的最后一项没有正确处理(与 中的前导“.”抑制逻辑交互skipname()
),因此“.” 从不匹配,但“..”设法匹配。(glob_patscan
又名PATSCAN
感谢宏游戏。)
其中任何一个也有效:
$ echo /@(usr|.|)/@(local|.|)/@(share|.|)/
/./././ /usr/././ /usr/./share/ /usr/local/./ /usr/local/share/
$ echo /@(usr|.|.)/@(local|.|.)/@(share|.|.)/
/./././ /usr/././ /usr/./share/ /usr/local/./ /usr/local/share/
Run Code Online (Sandbox Code Playgroud)
所以答案是子模式顺序不重要,也不重要,但是当最后一项是“.”时,似乎一个错误会导致问题。
归档时间: |
|
查看次数: |
123 次 |
最近记录: |