문제

I'm making a program in bash that creates a histoplot, using numbers I have created. The numbers are stored as such (where the 1st number is how many words are on a line of a file, and the 2nd number is how many times this amount of words on a line comes up, in a given file.)

 1  1
 2  4
 3  1
 4  2

this should produce:

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

BUT the output I'm getting is:

 1 #
 2 #
 3 #
 4 # 

however the for loop is not recognising that my variable "hashNo" is a number.

 #!/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

the code works if I replace hashNo with a number (eg 4 makes 4 hashes in my output) but it needs to be able to change with each line (no all lines on a file will have the same amount of chars in them.

thanks for any help :D

도움이 되었습니까?

해결책

A sequence expression in bash must be formed from either integers or characters, no parameter substitutions take place before hand. That's because, as per the bash doco:

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

In other words, brace expansion (which includes the sequence expression form) happens first.

In any case, this cries out to be done as a function so that it can be done easily from anywhere, and also made more efficient:

#!/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)"

which outputs, as desired:

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

The use of the first loop (doing ten hashes at a time) will almost certainly be more efficient than adding one character at a time and you can, if you wish, do a size-50 loop before that for even more efficiencies if your values can be larger.

다른 팁

I tried this for (( i=1; i<=$hashNo; i++ )) for the for loop, it seems to be working

Your loop should be

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

Also you can stick with your loop by the use of eval and command substitution $()

for i in $(eval echo {1..$hashNo})
do
   hashes+="#"    
done  
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top