本文共 2136 字,大约阅读时间需要 7 分钟。
使用
brace expansion的序列表达形式({< numFrom> ..< numTo>})的变量仅适用于ksh和zsh,但遗憾的是,不在bash中(并且(大多数情况下)严格来说仅限POSIX特征的shell如破折号根本不支持撑杆扩张,因此应完全避免撑杆扩展/ bin / sh).
鉴于你的症状,我假设你正在使用bash,你只能在序列表达式中使用文字(例如{1..3});从manual(强调我的):
Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result.
换句话说:在评估大括号表达式时,尚未扩展(解析)变量引用;因此,将$var1和$var2等文字解释为序列表达式上下文中的数字会失败,因此大括号表达式被视为无效且未展开.
但请注意,变量引用是扩展的,即在整体扩展的后期阶段;在手边的情况下,字面结果是单个单词'{1..4}’ – 展开变量值的未展开大括号表达式.
虽然括号扩展的列表形式(例如,{foo,bar))以相同的方式扩展,但后来的变量扩展在那里不是问题,因为不需要预先解释列表元素;例如{$var1,$var2}正确导致2个单词1和4.
至于为什么变量不能用于序列表达式:历史上,括号扩展的列表形式首先出现,当后来引入序列表达形式时,扩展的顺序已经固定.
有关支架扩展的一般概述,请参阅this answer.
解决方法
注意:变通方法的重点是数字序列表达式,如问题所示;基于eval的变通方法还演示了如何使用不太常见的字符序列表达式的变量,这些表达式产生英文字母范围(例如,{a..c}以产生b c).
一个小小的警告是seq不是POSIX实用程序,但大多数现代的类Unix平台都有它.
要稍微改进一下,使用seq的-f选项提供printf样式的格式字符串,并演示两位数的零填充:
seq -f '%02.f.txt' $var1 $var2 | xargs ls # '%02.f'==zero-pad to 2 digits, no decimal places
请注意,要使其完全健壮 – 如果生成的单词包含空格或制表符 – 您需要使用嵌入式引用:
seq -f '"%02.f a.txt"' $var1 $var2 | xargs ls
然后看到01 a.txt,02 a.txt,…正确保留了参数边界.
如果你想首先在Bash数组中稳健地收集结果单词,例如${words [@]}:
IFS=$'\n' read -d '' -ra words <
ls "${words[@]}"
以下是纯Bash解决方法:
使用Bash功能的有限解决方法是使用eval:
var1=1 var2=4
# Safety check
(( 10#$var1 + 10#$var2 || 1 )) 2>/dev/null || { echo "Need decimal integers." >&2; exit 1; }
ls $(eval printf '%s\ ' "{$var1..$var2}.txt") # -> ls 1.txt 2.txt 3.txt 4.txt
您可以将类似的技术应用于字符序列表达式;
var1=a var2=c
# Safety check
[[ $var1 == [a-zA-Z] && $var2 == [a-zA-Z] ]] || { echo "Need single letters."; exit 1; }
ls $(eval printf '%s\ ' "{$var1..$var2}.txt") # -> ls a.txt b.txt c.txt
注意:
>预先执行检查以确保$var1和$var2包含十进制整数或单个英文字母,这样可以安全地使用eval.通常,使用带有未经检查的输入的eval是一种安全风险,因此最好避免使用eval.
>鉴于eval的输出必须在此处不加引号传递给ls,以便shell通过单词拆分将输出拆分为单个参数,这仅在生成的文件名不包含嵌入空格或其他shell元字符时才有效.
一个更强大但更麻烦的纯Bash解决方法,使用数组创建等效的单词:
var1=1 var2=4
# Emulate brace sequence expression using an array.
args=()
for (( i = var1; i <= var2; i++ )); do
args+=( "$i.txt" )
done
ls "${args[@]}"
>此方法不存在安全风险,也适用于带有嵌入式shell元字符(如空格)的结果文件名.>可以通过将i替换为例如i = 2来以2为增量步长来实现自定义增量.>实现零填充需要使用printf;例如,如下:args =(“$(printf’?d.txt’”$i“)”)# – > ’01 .txt’,’02 .txt’,…
转载地址:http://irqhp.baihongyu.com/