Linux   发布时间:2022-05-08  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了linux – 如何使用大括号扩展变量大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
参见英文答案 > Brace expansion with variable?                                     6个
我有四个文件:

@H_502_9@

@H_502_9@

1.txt  2.txt  3.txt  4.txt

在linux shell中,我可以使用:
ls {1..4} .txt列出所有四个文件
但如果我设置两个变量:var1 = 1和var2 = 4,如何列出这四个文件?
那是:@H_502_9@

@H_502_9@

var1=1
var2=4
ls {$var1..$var2}.txt  # error

什么是正确的代码?@H_502_9@

解决方法

使用 brace expansion的序列表达形式({< numFrom> ..< numTo>})的变量仅适用于ksh和zsh,但遗憾的是,不在bash中(并且(大多数情况下)严格来说仅限POSIX特征的shell如破折号根本不支持撑杆扩张,因此应完全避免撑杆扩展/ bin / sh).

@H_502_9@

鉴于你的症状,我假设你正在使用bash,你只能在序列表达式中使用文字(例如{1..3});从manual(强调我的):@H_502_9@

@H_502_9@

换句话说:在评估大括号表达式时,尚未扩展(解析)变量引用;因此,将$var1和$var2等文字解释为序列表达式上下文中的数字会失败,因此大括号表达式被视为无效且未展开.
但请注意,变量引用是扩展的,即在整体扩展的后期阶段;在手边的情况下,字面结果是单个单词'{1..4}’ – 展开变量值的未展开大括号表达式.@H_502_9@

虽然括号扩展的列表形式(例如,{foo,bar))以相同的方式扩展,但后来的变量扩展在那里不是问题,因为不需要预先解释列表元素;例如{$var1,$var2}正确导致2个单词1和4.
至于为什么变量不能用于序列表达式:历史上,括号扩展的列表形式首先出现,当后来引入序列表达形式时,扩展的顺序已经固定.
有关支架扩展的一般概述,请参阅this answer.@H_502_9@

解决方法@H_502_9@

注意:变通方法的重点是数字序列表达式,如问题所示;基于eval的变通方法还演示了如何使用不太常见的字符序列表达式的变量,这些表达式产生英文字母范围(例如,{a..c}以产生b c).@H_502_9@

可以使用基于seq的解决方法,as demonstrated in Jameson’s answer.@H_502_9@

一个小小的警告是seq不是POSIX实用程序,但大多数现代的类Unix平台都有它.@H_502_9@

要稍微改进一下,使用seq的-f选项提供printf样式的格式字符串,并演示两位数的零填充:@H_502_9@

@H_502_9@

seq -f '%02.f.txt' $var1 $var2 | xargs ls # '%02.f'==zero-pad to 2 digits,no decimal places

请注意,要使其完全健壮 – 如果生成的单词包含空格或制表符 – 您需要使用嵌入式引用:@H_502_9@

@H_502_9@

seq -f '"%02.f a.txt"' $var1 $var2 | xargs ls

然后看到01 a.txt,02 a.txt,…正确保留了参数边界.@H_502_9@

如果你想首先在Bash数组中稳健地收集结果单词,例如${words [@]}:@H_502_9@

@H_502_9@

IFS=$'\n' read -d '' -ra words < <(seq -f '%02.f.txt' $var1 $var2)
ls "${words[@]}"

以下是纯Bash解决方法:@H_502_9@

使用Bash功能的有限解决方法是使用eval:@H_502_9@

@H_502_9@

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

您可以将类似的技术应用于字符序列表达式;@H_502_9@

@H_502_9@

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

注意:@H_502_9@

>预先执行检查以确保$var1和$var2包含十进制整数或单个英文字母,这样可以安全地使用eval.通常,使用带有未经检查的输入的eval是一种安全风险,因此最好避免使用eval.
>鉴于eval的输出必须在此处不加引号传递给ls,以便shell通过单词拆分将输出拆分为单个参数,这仅在生成的文件名不包含嵌入空格或其他shell元字符时才有效.@H_502_9@

一个更强大但更麻烦的纯Bash解决方法,使用数组创建等效的单词:@H_502_9@

@H_502_9@

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’,…@H_502_9@

大佬总结

以上是大佬教程为你收集整理的linux – 如何使用大括号扩展变量全部内容,希望文章能够帮你解决linux – 如何使用大括号扩展变量所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: