Brace expansion with variable?
本问题已经有最佳答案,请猛点这里访问。
1 2 3 4 5 | #!/bin/sh for i in {1..5} do echo"Welcome" done |
会工作,显示欢迎5次。
1 2 3 4 5 6 | #!/bin/sh howmany=`grep -c $1 /root/file` for i in {1..$howmany} do echo"Welcome" done |
不行!
有任何想法吗?
无法在序列括号表达式中使用变量的变通方法:
-
如果意图只是迭代一个范围内的数字 - 如OP的情况 - 最好的选择不是使用大括号扩展,而是使用bash的C风格循环 - 请参阅user000001的答案。
- 如果具体的数字并不重要,你只需要执行指定次数的循环体,Cole Tierney的答案就是一个选项。
-
如果需要使用支撑膨胀:
-
如果您不需要列表中的数字具有前缀或后缀,请使用带有不带引号的命令替换的
seq 实用程序(小警告:seq 不是POSIX实用程序,但它可以广泛使用);例如-
echo $(seq 3) - >1 2 3 ;起始编号1 隐含-
echo $(seq -f '%02.f' 3) - >01 02 03 - 零填充
-
-
echo $(seq 2 4) - >2 3 4 ;显式的开始和结束数字 -
echo $(seq 1 2 5) - >1 3 5 ;自定义增量(中间的2 )
-
-
如果您需要列表中的数字有前缀或后缀,您有几个选择:
-
使用
seq 实用程序及其-f 选项提供printf 样式的格式字符串(如上面用于零填充),或基于eval 的纯Bash解决方法(需要额外注意!)或构建循环中的数组,所有这些都在这个答案中详述。 -
您还可以考虑一般性地实现该功能,例如通过编写自定义shell函数或使用诸如
awk 或perl 之类的实用程序的自定义脚本。
-
使用
-
使用驱动序列括号表达式的变量安全使用
事先验证变量,以确保它们包含十进制整数。
1 2 3 4 5 6 | from=1 to=3 # sample values # Ensure that $from and $to are decimal numbers and abort, if they are not. (( 10#$from + 10#$to || 1 )) 2>/dev/null || { echo"Need decimal integers">&2; exit 1; } eval echo"A{$from..$to}" # -> 'A1 A2 A3' |
支架扩展概述
大括号扩展的主要目的是扩展到一个令牌列表,每个令牌都有一个可选的前缀和/或后缀;大括号扩展必须是不加引号的,有两种风格:
-
逗号分隔字符串的固定系列(列表) - 支持的变量
- 指定并扩展为固定数量的令牌(2个或更多);例如。:
-
echo A{b,c,d} - >Ab Ac Ad ,即3个令牌,如args的数量所暗示的那样。 -
echo {/,$HOME/}Library ,例如, - >/Library /User/jdoe/Library - 支持变量引用 - 甚至是全局 - 但请注意,在正常评估过程中,在结果扩展后,它们会扩展。
-
带有
.. 的序列表达式(范围),通常是数字 - 不支持的变量-
扩展为可变数量的标记,由文字起点和终点驱动(由于历史原因,不支持使用变量 - 请参阅有关user000001答案的注释):
-
[罕见]字符串:仅允许单个英文字母;例如
{a..c} -
数字:仅十进制整数;例如,
{1..10} ,{10..1} ,{-1..2} -
带前缀和后缀的示例:
A{1..3}# - >A1# A2# A3# -
带有变量的破坏示例:
{$from..$to} # !! FAILS -$from 和$to 被解释为文字,因此不会被识别为单个字母或十进制整数 - 不执行大括号扩展(参见下文)。-
相反,使用变量确实可以在
zsh 和ksh 中使用。
-
相反,使用变量确实可以在
-
带前缀和后缀的示例:
-
bash 4+增加了两个功能:
-
可选的增量步长值:
-
echo A{1..5..2} - >A1 A3 A5 - 数字加2
-
-
零垫的能力:
-
echo A{001..003} - >A001 A002 A003
-
-
可选的增量步长值:
-
[罕见]字符串:仅允许单个英文字母;例如
-
扩展为可变数量的标记,由文字起点和终点驱动(由于历史原因,不支持使用变量 - 请参阅有关user000001答案的注释):
-
无法扩展无效的大括号表达式(将其视为常规的不带引号的字符串,将
{ 和} 视为文字):-
echo {} - >'{}' - 作为大括号expr无效:至少需要2个, - 分离的标记-
例如,这允许使用带有
find 的未加引号的{} 。
-
例如,这允许使用带有
-
echo {1..$to} - >'{1.. - 作为大括号expr无效。在}' bash 中:不支持变量;但是,在ksh 和zsh 中有效。 -
(
fish ,相比之下,扩展任何{...} 序列;类似地,zsh 具有选项BRACE_CCL (默认为OFF),用于扩展{..} 内的单个字符,这有效地导致任何非空{...} 序列的扩展。)
-
在扩展变量之前评估大括号扩展。 你需要一个c风格的循环代替:
1 2 3 4 | for ((i=1;i<=howmany;i++)) do echo"Welcome" done |
问题是"支撑扩展"是在"可变扩展"之前执行的
1 | for i in $(seq 1 $howmany) |
作为@damienfrancois说,或者,如果你愿意:
1 | for i in $(eval echo '{$start..10}') |
可能会这样做,但不要将它用于每个人的理智。
创建一个序列来控制你的循环
1 2 3 | for i in $(seq 1 $howmany); do echo"Welcome"; done |
你也可以使用while循环:
1 2 3 | while ((howmany--)); do echo"Welcome" done |
在这种情况下我们也可以使用
1 2 3 4 | howmany=`grep -c $1 /root/file` for i in $(eval echo {1..$howmany}); do echo"Welcome" done |