Bash for循环参数意外行为

时间:2014-04-25 04:44:35

标签: linux bash for-loop terminal

我正在用bash创建一个程序,使用我创建的数字创建一个histoplot。这些数字是这样存储的(其中第一个数字是文件行上有多少个单词,第二个数字是给定文件中一行中单词数量出现的次数。)

 1  1
 2  4
 3  1
 4  2

这应该产生:

 1  #
 2  ####
 3  #
 4  ##

但我得到的输出是:

 1 #
 2 #
 3 #
 4 # 

然而for循环没有意识到我的变量“hashNo”是一个数字。

 #!/bin/bash
 if [ -e $f ] ; then
         while read line    
     do     
         lineAmnt=${line% *}
         hashNo=${line##* }
      #VVVV Problem is this line here VVVV 
             for i in {1..$hashNo} 
             #This line ^^^^^^^ the {1..$hashNo} 
             do
             hashes+="#"    
             done   
         printf "%4s" $lineAmnt 
         printf " $hashes\n"
         hashes=""  
     done < $1
 fi

如果我用一个数字替换hashNo(例如4在我的输出中产生4个哈希),代码就可以工作但是它需要能够随每一行改变(文件中的所有行都不会有相同数量的字符)

感谢您的帮助:D

3 个答案:

答案 0 :(得分:1)

你的循环应该是

for ((i=0; i<hashNo; i++))
do
      hashes+="#"    
done  

此外,您可以使用eval和命令替换$()

来坚持使用循环
for i in $(eval echo {1..$hashNo})
do
   hashes+="#"    
done  

答案 1 :(得分:1)

我为for循环尝试了这个for (( i=1; i<=$hashNo; i++ )),它似乎正在工作

答案 2 :(得分:1)

bash中的序列表达式必须由整数或字符组成,事先不进行参数替换。这是因为,根据bash doco:

  

扩展的顺序是:大括号展开,波浪扩展,参数,变量和算术扩展以及命令替换(以从左到右的方式完成),单词拆分和路径名扩展。

换句话说,大括号扩展(包括序列表达形式)首先发生

在任何情况下,这都是一种功能,因此可以从任何地方轻松完成,并且效率更高:

#!/bin/bash

hashes() {
    sz=$1
    while [[ $sz -ge 10 ]]; do
        printf "##########"
        ((sz -= 10))
    done
    while [[ $sz -gt 0 ]]; do
        printf "#"
        ((sz--))
    done
}

echo 1 "$(hashes 1)"
echo 2 "$(hashes 4)"
echo 3 "$(hashes 1)"
echo 4 "$(hashes 2)"

根据需要输出:

1 #
2 ####
3 #
4 ##

第一个循环的使用(一次做十个哈希)几乎肯定会比一次添加一个字符更有效率,如果你愿意,你可以在此之前做一个50的循环,以获得更高的效率如果你的价值可以更大。