ghostrider
ghostrider

Reputation: 5259

getting result from awk and printing it into a file

I am using awk to get compute some sums and I want to store them in a file.

here is my input file:

misses 15
hit 18
misses 20
hit 31

And I want to print the total misses, and total hits in a file.

If I run this:

awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt 

I see them in the terminal.

Now I want to write the in a file:

I tried this:

#!/bin/bash
 awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt

echo misses $misses > $1; #first one overwrites the previous $1 is the argument given in the command line
echo hits $hits>> $1; # all the othes append to the .txt file

but $misses, and $hits do not have value.

I also tried this:

#!/bin/bash
result= $(echo $output | awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt )
# $NF if I want the last column
echo $result

that I saw on the web, in order to see what $result will return me but I get this error:

./test2.sh: line 2: Hits:: command not found

Upvotes: 0

Views: 575

Answers (3)

nullrevolution
nullrevolution

Reputation: 4137

simply redirect the output of the awk command:

awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt >file.txt

the redirection operator > can be appended to any shell command to redirect its standard output to a file. changing it to >> appends the command's output to the file instead of completely overwriting the file, as you noticed.

edit:

the reason this didn't work:

#!/bin/bash
 awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt

echo misses $misses > $1; #first one overwrites the previous $1 is the argument given in the command line
echo hits $hits>> $1; # all the othes append to the .txt file

is because $misses and $hits are local variables to the awk script. thus the shell has no knowledge of them outside that statment, so when you try to echo them, you get blanks.

and this doesn't work:

#!/bin/bash
result= $(echo $output | awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt )
# $NF if I want the last column
echo $result

for multiple reasons.

1) when assigning variables in bash, you cannot have whitespace around the equal sign, so the second line must begin:

`result=$(echo...`

2) the echo statement inside your substitution (echo $output) is unnecessary. this is because a) $output is undefined so echo produces no output, and b) the second statement in the pipeline (the awk statement) completely ignores the standard output of the command preceding it in the pipeline anyway since you specified a filename for it to act on (t.txt). so the second line could just be:

result=$(awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt)

3) the echo statement at the end will display the results all on one line, despite the fact that the awk statement prints two lines. this is because you did not quote the variable in your echo statement. try this instead:

echo "$result"

as a rule in bash scripting, you should ALWAYS quote the variables you are passing or printing, unless you know for sure why you don't want to.

hope that helps you learn a bit more about what you were trying!

Upvotes: 1

Hai Vu
Hai Vu

Reputation: 40733

Here is a more compact solution:

#!/bin/bash
awk '
    {tally[$1] += $2}
    END {
        for (outcome in tally) {
            print outcome ":", tally[outcome]
        }
    }' t.xt > $1

You don't have to initialize variables in AWK. The first time you use it, AWK will assume 0 for number, or "" for string, depend on the context.

Upvotes: 0

chepner
chepner

Reputation: 531275

hits and misses are only variables inside awk, not in the shell after awk exits. Just do the following:

#!/bin/bash
awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt > $1

In your second attempt, you cannot put a space after the '=':

result=$(echo $output | awk 'BEGIN { hits=0; misses=0; } /^hit/{ hits+=$2}; /^misses/{misses+=$2}; END {print "Hits: " hits "\nMisses: " misses }' t.txt )

Upvotes: 3

Related Questions