#!/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,在运行脚本时是特定的。

有什么想法吗?

评论

添加一个echo $ howmany进行调试以检查IS 5'不起作用'==>可能意味着任何事情,发送运行的完整输出。

您可以使用seq命令。对于$(seq 1 $ howmany)中的i

@ user2701753,我尝试使用:x = 5;为{1 .. $ x}中的i;做回声“嗨”;完成,也行不通。它只打印一次Hi。

我做了一些建议的评论:i.imgur.com/xCza7Fv.png您可以在图片中看到上面的输出。

#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函数或具有实用程序(例如awkperl)的自定义脚本。






安全使用带有驱动序列括号表达式的变量的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中:不支持变量;但是,在kshzsh中有效。
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