tags:

views:

580

answers:

5
#!/bin/bash

for ((var=0; var<20; var++))
do
echo " Number is: $(grep 'Multiple_Frame = echo **$var**'  20mrf.txt | wc -l)" >>statisic.txt 

done

This shell program cannot produce correct result which maybe the reason of wrong variable returning in the second grep command.

How can I grep a variable within the second echo sentence? to grep different things according to the var changing?

Many thanks!

+1  A: 

You have to store each substitution in a variable. Like this:

#!/bin/bash

for ((var=0; var < 20; var++))
do

count=`grep "Multiple_Frame = $var"  20mrf.txt | wc -l`
echo " Number is: $count" >> statisic.txt 

done
NawaMan
after I split the command as what you told me, I get the following error info../loop_count_reference_frame_no.sh: line 10: grep "Multiple_Frame = $var" 20mrf.txt | wc -l: command not found
MaiTiano
maybe the single quote cannot generate correct grep result and send it to the new "count" variable.
MaiTiano
I know what is the wrong place... I should use esc not simple single quote. Thanks anyway.
MaiTiano
Sorry, I just see your comment. Yes, those are '`' (Grave accent) not a single quote. :-D
NawaMan
A: 

The string inside $(...) is quoted with single quotes ('...') this quoting prevents the variable expansion. Use Double quotes instead. In your case:

#!/bin/bash

for ((var=0; var<20; var++))
do
echo " Number is: $(grep 'Multiple_Frame = echo **'"$var"'**'  20mrf.txt | wc -l)" >>statisic.txt 

done

Note that in this example, it seems like the double quotes for the echo command are already opened, but you should note that the $(...) is evaluated first, and there is no double quotes inside it. So the change here is to close the single quote of the grep open double quote instead, and close the double quotes and reopen single quote later.

This lengthy explanation illustrates the benefit of breaking the expression apart, as suggested by other answers.

Chen Levy
closing single quote of grep cannot help it to produce a correct result. anyway, thank you~
MaiTiano
+1  A: 

Ok, the second [sic] problem is with your quoting on line 5. The reference to $var will never be expanded because it's contained within single quotes. You can fix that by replacing the single quotes (') with escaped double quotes (\").

The first [sic] problem is that you're trying to do too much in a single line, which causes your nesting problem with quotes. Break the line up into multiple commands, storing intermediary results as necessary. Yeah, it might run a tad slower, but you'll save a LOT of time debugging and maintaining it.

Trader's Second Law: If you have to choose between optimizing for performance, and optimizing for maintainability, ALWAYS choose to make your code more maintainable. Computers get faster all the time; Programmers don't.

Craig Trader
+1  A: 

As others have stated, the problem is that the single quotes prevent expansion of the variable. However, using $() allows you to use double quotes:

echo " Number is: $(grep "Multiple_Frame = echo **$var**"  20mrf.txt | wc -l)" >>statisic.txt

although I suspect something like this is what you meant:

echo " Number is: $(grep "Multiple_Frame = $var"  20mrf.txt | wc -l)" >>statisic.txt

You should also be aware that grep has an option to output the count so you can omit wc:

echo " Number is: $(grep -c "Multiple_Frame = $var"  20mrf.txt)" >>statisic.txt
Dennis Williamson
+1  A: 

@OP, doing what you do that way is rather inefficient. You are calling grep and wc 20 times on the same file. Open the file just once, and get all the things you want in 1 iteration of the file contents. Example in bash 4.0

declare -A arr
while read -r line
do  
    case "$line" in
        *"Multiple_Frame ="*) 
            line=${line#*Multiple_Frame = }
            num=${line%% *}
            if [ -z ${number_num[$num]} ] ;then
               number_num[$num]=1
            else
                number_num[$num]=$(( number_num[$num]+1 ))
            fi
            ;;
    esac    
done <"file"
for i in "${!number_num[@]}"
do
    echo "Multiple_Frame = $i has ${number_num[$i]} counts"
done

similarly, you can use associative arrays in gawk to help you do this task.

gawk '/Multiple_Frame =/{
  sub(/.*Multiple_Frame = /,"")
  sub(/ .*/,"")
  arr["Multiple_Frame = "$0]=arr["Multiple_Frame = "$0]+1  
}END{
    for(i in arr) print i,arr[i]
}' file
OMG, your program is amazing.Since I am a such a newbie to those Linux programming, you are really giving me a good lesson.Thanks.~
MaiTiano