Leo*_*mon 11 bash brace-expansion
我正在尝试扩展包含通配符和大括号内指定的扩展集合的字符串。如下例所示,似乎没有任何效果。变量firstList
扩大罚款,但没有secondList
,thirdList
还是fourthList
扩展正确。我也尝试过各种版本,eval
但都没有奏效。任何帮助,将不胜感激
#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"
Run Code Online (Sandbox Code Playgroud)
小智 9
这 外壳扩展*
仅当外壳未引述任何引用停止扩张。
此外,大括号扩展需要不加引号才能被 shell 扩展。
这项工作(让我们使用 echo 查看 shell 做了什么):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Run Code Online (Sandbox Code Playgroud)
即使有一些其他名称的文件:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Run Code Online (Sandbox Code Playgroud)
重要的是我们要了解它为什么起作用。这是因为扩展的顺序。首先是“支撑扩展”,然后是(最后一个)“路径名扩展”(又名全局扩展)。
Brace --> Parameter (variable) --> Pathname
Run Code Online (Sandbox Code Playgroud)
我们可以暂时关闭“路径名扩展”:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
Run Code Online (Sandbox Code Playgroud)
“路径名扩展”接收两个参数:*.ext1
和*.ext2
。
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Run Code Online (Sandbox Code Playgroud)
问题是我们不能为大括号扩展使用变量。
之前已经多次解释在“支撑扩展”中使用变量
要扩展作为“变量扩展”结果的“大括号扩展”,您需要使用eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Run Code Online (Sandbox Code Playgroud)
大括号 -->变量--> Glob || -->大括号--> 变量 --> Glob
........这里引用 -->^^^^^^ || 评估 ^^^^^^^^^^^^^^^^^^^^^^^^^
文件名的值不会给 eval 带来执行问题:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Run Code Online (Sandbox Code Playgroud)
但是 的值$list
可能是不安全的。但是, 的值$list
由脚本编写者设置。脚本编写者控制eval
: 只是不使用外部设置的$list
. 尝试这个:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Run Code Online (Sandbox Code Playgroud)
另一种选择(没有 eval)是使用 Bash“扩展模式”:
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Run Code Online (Sandbox Code Playgroud)
注意:请注意,对于带有空格或换行符的文件名,两种解决方案(eval 和模式)(如所写)都是安全的。但是对于$list
带有空格的会失败,因为$list
没有引用或 eval 删除了引号。
考虑:
secondList='*.{ext1,ext2}'
ls $secondList
Run Code Online (Sandbox Code Playgroud)
问题是大括号扩展是在变量扩展之前 完成的。这意味着,在上面,从不执行大括号扩展。
这是因为,当 bash 第一次看到命令行时,没有大括号。等secondList
扩大之后,就晚了。
以下将起作用:
$ s='*'
$ ls $s.{ext1,ext2}
a.ext1 a.ext2 b.ext1 b.ext2
Run Code Online (Sandbox Code Playgroud)
这里,命令行有大括号,以便第一步可以执行大括号扩展。之后,$s
将 的值代入(变量扩展),最后进行路径名扩展。
man bash
解释扩展的顺序:
展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。
归档时间: |
|
查看次数: |
14956 次 |
最近记录: |