#!/bin/sh
for i in {1..5}
do
echo "Welcome"
done
可以工作,显示Welcome 5次。
#!/bin/sh
howmany=`grep -c /root/file`
for i in {1..$howmany}
do
echo "Welcome"
done
不起作用!
howmany
等于5,因为grep -c
的输出将显示为5。 $ 1是参数1,在运行脚本时是特定的。有什么想法吗?
#1 楼
创建一个序列来控制循环for i in $(seq 1 $howmany); do
echo "Welcome";
done
评论
seq不是POSIX标准化工具。它不能保证完全安装在POSIX系统上,更不用说以任何特定方式运行了。
–查尔斯·达菲(Charles Duffy)
2015年11月12日在21:39
#2 楼
无法在序列括号表达式中使用变量的解决方法:
如果目的只是迭代范围内的数字-如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
)的自定义脚本。安全使用带有驱动序列括号表达式的变量的
eval
的示例:变量已预先验证,以确保它们包含十进制整数。
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
支持变量引用(甚至glob),但请注意,它们在括号扩展后会扩展,其结果是在正常求值过程中扩展。
序列表达式(范围)带有
..
,通常是数值-不支持的变量扩展为可变数量的令牌,由文字的起点和终点驱动(出于历史原因,不支持使用变量-请参阅对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
无效的括号表达式不会展开(像常规的未加引号的字符串一样,将
{
和}
视为文字):echo {}
-> '{}'
-作为括号expr无效。:至少需要2个,
分隔的令牌例如,这允许将未引用的
{}
与find
一起使用。echo {1..$to}
-> '{1..<value-of-$to>}'
-作为括号表达式无效。在bash
中:不支持变量;但是,在ksh
和zsh
中有效。(
fish
可以扩展任何{...}
序列;类似地,zsh
具有选项BRACE_CCL
(默认情况下为OFF),用于扩展{..}
内部的各个字符,这实际上会导致扩展任何非空的{...}
序列。)#3 楼
在扩展变量之前先评估括号扩展。您需要使用c样式的for循环:for ((i=1;i<=howmany;i++))
do
echo "Welcome"
done
评论
这是为什么?先扩展变量,然后扩展括号表达式是否更有意义?
– Shahbaz
2013年10月17日17:00
@Shahbaz也许是有道理的。但这就是他们设计语言的方式。
–user000001
13年10月17日在17:01
@Shahbaz可以,但是bash根本没有。最初,括号扩展是为将a {b,c} d扩展为abd acd而设计的; {1..10}语法是后来添加的,但是扩展顺序已经确定。我怀疑更改括号内的参数并不值得。就其价值而言,zsh确实允许在括号扩展内进行参数扩展。
–chepner
13-10-17在17:02
@chepner:很高兴知道;起初我很困惑,它确实可以使用字符串列表形式的变量:v1 = a v2 = b;回声{$ v1,$ v2}->'a b'。 Bash首先将其转换为令牌列表“ $ v1 $ v2”(括号扩展),然后扩展变量引用(参数扩展),对吗?由于必须保留此扩展顺序以实现向后兼容性,因此无法使用数字范围形式的变量,因为在不知道变量引用表示什么数字的情况下,bash无法创建令牌列表,因为它不知道什么以及有多少要创建的令牌。
–mklement0
2015年3月12日19:37
@chepner:还很高兴知道您可以在zsh中使用变量引用。同上ksh。
–mklement0
15年3月12日在19:38
#4 楼
问题是“括号扩展”是在“变量扩展”之前执行的。for i in $(seq 1 $howmany)
如@damienfrancois所述,或者,如果您愿意: >
for i in $(eval echo '{$start..10}')
可能会这样做,但不要为了所有人的理智而使用它。
#5 楼
您还可以使用while循环:while ((howmany--)); do
echo "Welcome"
done
#6 楼
在这种情况下,我们也可以使用eval
:howmany=`grep -c /root/file`
for i in $(eval echo {1..$howmany}); do
echo "Welcome"
done
评论
添加一个echo $ howmany进行调试以检查IS 5'不起作用'==>可能意味着任何事情,发送运行的完整输出。您可以使用seq命令。对于$(seq 1 $ howmany)中的i
@ user2701753,我尝试使用:x = 5;为{1 .. $ x}中的i;做回声“嗨”;完成,也行不通。它只打印一次Hi。
我做了一些建议的评论:i.imgur.com/xCza7Fv.png您可以在图片中看到上面的输出。