如何使用括号扩展变量 [英] how to use variables with brace expansion

查看:174
本文介绍了如何使用括号扩展变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有四个文件:

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

在Linux shell中,我可以使用:
LS {} 1..4 .TXT 来列出所有的四个文件
但如果我设置了两个变量:VAR1 = 1和var2 = 4,如何列出的四个文件?
那就是:

in linux shell, I could use : ls {1..4}.txt to list all the four files but if I set two variables : var1=1 and var2=4, how to list the four files? that is:

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

什么是正确code?

what is the correct code?

推荐答案

使用的变量的用的序列-EX pression形式的( {< numFrom> ..< numTo>} )的括号扩展 仅在 KSH 和的zsh ,但不幸的是,未在庆典 (和(主要是)严格POSIX的功能 - 只贝壳,如破折号不支持括号扩展的所有的,所以括号扩展应该是避免 / bin / sh的共有)。

Using variables with the sequence-expression form ({<numFrom>..<numTo>}) of brace expansion only works in ksh and zsh, but, unfortunately, not in bash (and (mostly) strictly POSIX-features-only shells such as dash do not support brace expansion at all, so brace expansion should be avoided with /bin/sh altogether).

由于你的症状,我假设你正在使用庆典在这里你可以只使用的文本的顺序前pressions (例如, {1..3} );从手动(重点煤矿)

Given your symptoms, I assume you're using bash, where you can only use literals in sequence expressions (e.g., {1..3}); from the manual (emphasis mine):

支撑扩张的之前的任何其他扩展的,任何特殊的字符与其他扩展都在结果preserved执行。

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result.

在换句话说:是在一个括号前pression进行评估的时候,变量引用没有被扩大(解决),但;除preting的文本的如 $ VAR1 $ VAR2 如数字因此序列的前pression的情况下出现故障,所以的括号前pression被视为无效,不扩大的。结果
但是请注意,该变量的引用的扩大,即在整体扩张的稍后阶段;在本案字面结果就是一个字'{1..4} - 未展开前撑pression具有扩展的变量值

In other words: at the time a brace expression is evaluated, variable references have not been expanded (resolved) yet; interpreting literals such as $var1 and $var2 as numbers in the context of a sequence expression therefore fails, so the brace expression is considered invalid and as not expanded.
Note, however, that the variable references are expanded, namely at a later stage of overall expansion; in the case at hand the literal result is the single word '{1..4}' - an unexpanded brace expression with variable values expanded.

虽然列表的括号扩展(例如, {富,吧))展开同样的方式,后来变的形式扩张是不是一个问题出现,因为需要在前面的列表中的元素没有跨pretation;例如 {$ VAR1,$ VAR2} 正确导致2字 1 4 。结果
至于的为什么的变量不能按顺序前pressions使用:从历史上看,列表的括号扩展的形式首先出现,而当序列前pression后来形式引入,扩展的顺序已经固定。结果
对于括号扩展的概述,请参见这个答案

While the list form of brace expansion (e.g., {foo,bar)) is expanded the same way, later variable expansion is not an issue there, because no interpretation of the list elements is needed up front; e.g. {$var1,$var2} correctly results in the 2 words 1 and 4.
As for why variables cannot be used in sequence expressions: historically, the list form of brace expansion came first, and when the sequence-expression form was later introduced, the order of expansions was already fixed.
For a general overview of brace expansion, see this answer.

注:解决方法注重的数值的序列前pressions,如问题;在评估基于解决办法也表明与不常见的字符的序列前pressions,而产生的英语范围的使用变量信的(例如, {a..c} 制作 ABC )。

Note: The workarounds focus on numerical sequence expressions, as in the question; the eval-based workaround also demonstrates use of variables with the less common character sequence expressions, which produce ranges of English letters (e.g., {a..c} to produce a b c).

A SEQ 基于解决方法是可能的,的在詹姆逊的答案证明。

A seq-based workaround is possible, as demonstrated in Jameson's answer.

小需要注意的是 SEQ 不是POSIX工具,但大多数现代类Unix平台有它。

A small caveat is that seq is not a POSIX utility, but most modern Unix-like platforms have it.

要完善它一点点,使用的序列 -f 选项提供一个的printf 风格的格式字符串,并展示两位数零填充:

To refine it a little, using seq's -f option to supply a printf-style format string, and demonstrating two-digit zero-padding:

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

请注意,要使其充分强劲 - 的情况下,所产生的字包含空格或制表符 - 你需要聘请的嵌入式报价的:

Note that to make it fully robust - in case the resulting words contain spaces or tabs - you'd need to employ embedded quoting:

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

LS 然后看见 01 A.TXT 02 A.TXT ,...带参数的边界正确preserved。

ls then sees 01 a.txt, 02 a.txt, ... with the argument boundaries correctly preserved.

如果您要有力收集产生的词语的一个猛砸的阵列的第一,如 $ {字[@]}

If you want to robustly collect the resulting words in a Bash array first, e.g., ${words[@]}:

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


以下是的纯巴什解决方法:

A 限制的变通办法使用bash特性仅是为使用评估

A limited workaround using Bash features only is to use 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

您可以使用类似的技术,以一个 字符的序列前pression ;

You can apply a similar technique to a character sequence expression;

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 包含十进制整数或单英文字母,然后使其能够安全使用评估一般情况下,使用评估与选中的输入是一个安全隐患,并使用评估的因此最好避免

  • 鉴于从评估输出的必须的传递的不带引号 LS 在这里,让shell把通过文字分裂输出到各个参数,这仅在产生的文件名包含嵌入空格或其他shell元字符的工作。

  • A check is performed up front to ensure that $var1 and $var2 contain decimal integers or single English letters, which then makes it safe to use eval. Generally, using eval with unchecked input is a security risk and use of eval is therefore best avoided.
  • Given that output from eval must be passed unquoted to ls here, so that the shell splits the output into individual arguments through words-splitting, this only works if the resulting filenames contain no embedded spaces or other shell metacharacters.

A 更健壮,更麻烦的纯巴什解决方法使用数组以创建相同的单词:

A more robust, but more cumbersome pure Bash workaround to use an array to create the equivalent words:

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 + = 2 来一步的增量为2

  • 实施的零填充的需要使用的printf的;例如,如下所示:搜索
    ARGS + =($(printf的'%02d.txt'$ I))# - &GT; '01 .TXT','02 .TXT,...

    • This approach bears no security risk and also works with resulting filenames with embedded shell metacharacters, such as spaces.
    • Custom increments can be implemented by replacing i++ with, e.g., i+=2 to step in increments of 2.
    • Implementing zero-padding would require use of printf; e.g., as follows:
      args+=( "$(printf '%02d.txt' "$i")" ) # -> '01.txt', '02.txt', ...
    • 这篇关于如何使用括号扩展变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆