我有一个名为 except.sh 的 bash 脚本,它传递了一个文件/目录列表,如下所示:
$ ls
a b c d/
$ ./except.sh b c
当调用 except 这种方式时,它应该扩展为 a d/
即除给定名称之外的所有文件/目录。
下面是我尝试实现的方法:
#!/usr/bin/env bash
# enable extended globbing
shopt -s extglob
# set IFS to | so that $* expands correctly
IFS='|'
printf '%s' !("$*")
给定 b c
作为参数,最后一行应该展开为
printf '%s' !(b|c)
导致 a d
被打印。但令我惊讶的是,
abcd
被打印出来。我做错了什么?
最佳答案
问题是$*
是在双引号里的,这意味着它的内容不会被当作一个模式,就像echo "*"
不会展开一样星号。将外部模式与内部引用部分组合会自动转义后者,因此 !("b|c")
被视为 !(b\|c)
。对不存在的 b|c
文件的否定自然会扩展到目录中的所有文件。
另一个问题是扩展的 globbing 被设置为 |
的 IFS
弄乱了,所以你必须在扩展模式之前重置它。因此,必须分两步进行扩展:首先计算模式,然后重置IFS
并扩展它:
#!/usr/bin/env bash
# enable extended globbing
shopt -s extglob
# temporarily set IFS to | so that $* expands to part an extended pattern
old_ifs=$IFS
IFS='|'
pattern="!($*)"
IFS=$old_ifs
printf '%s' $pattern
关于bash - 扩展的 glob 没有按预期扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14197202/