I have the below code in a bash file called ‘findError.sh’:
#!/bin/bash
filename="$1"
formatindicator="\"|\""
echo "$formatindicator"
formatarg="\$1"
echo "$formatarg"
count=`awk -F$formatindicator '{print $formatarg}' $filename | perl -ane '{ if(m/ERROR/) { print } }' | wc -l `
command="awk -F$formatindicator '{print $formatarg}' $filename | perl -ane '{ if(m/ERROR/) { print } }' | wc -l"
echo $command
echo $count
I then run it at the command line like so:
sh findError.sh test.dat
But It gives me a different count than running the command that was echoed?? How is this possible?
ie
The $command that is echoed back is:
awk -F"|" '{print $1}' test.dat | perl -ane '{ if(m/ERROR/) { print } }' | wc -l
But the $count that is echoed back is:
3
However if I just run this one line below at the command line (not through the script) – the result is 0:
awk -F"|" '{print $1}' test.dat | perl -ane '{ if(m/ERROR/) { print } }' | wc -l
Sample input file (test.dat):
sid|storeNo|latitude|longitude
2|1|-28.03720000
9|2
10
jgn352|1|-28.03ERROR720000
9|2|fdERRORkjhn422-405
0000543210|gfERRORdjk39
Notes: Using SunOS with bash version 4.0.17
You’re being too careful with your quotes around the format delimiter.
When you type:
The program (
awk) sees-F|as its first argument; the shell strips the double quotes.When you have:
You have preserved the double quotes in
$formatindicatorand thereforeawksees-F"|"as the delimiter, and uses the double quote as the delimiter.Use:
The difference is that the shell strips the quotes off
-F"$formatindicator"but doesn’t do that when$formatindicatoritself contains the double quotes.(NB: edited to retain back-quotes instead of the
$(...)notation that is (a) preferred and (b) was used in the first version of this answer. The$(...)notation was not recognized by the SunOS/bin/shwhich was, I believe, being used to execute the script. Bothbashandkshrecognize the$(...)notation, but the basic Bourne shell,/bin/sh, on Solaris 10 (SunOS 5.10) and earlier (I’ve not laid hands on Solaris 11) does not recognize$(...).)I note that any of
perl,awkorgrepcould be used to find the count of the error lines on its own, so the triplet ofawkpiped toperlpiped towcis not very efficient.It’s Perl, so TMTOWTDI; take your pick…
Side discussion
In the comments, we have concerns over how various parts of the script are being interpreted.
Let’s simplify this to (using part of my main answer):
The intention is to have the delimiter specified on the command line (which happens successfully) via the
-Foption. The issue, I expect, is “why does$formatargget expanded inside single quotes?”. And the answer is “Does it?”. I think not. So, what is happening, is thatawkis seeing the script{print $formatarg}. Sinceformatargis not assigned any value, it is equivalent to 0, so the script prints$0, which is the entire input line. Perl is quite happy to echo the line if it matches ERROR anywhere on the line, andwccouldn’t care less about what’s in the lines, so the result is approximately what was expected. The only time there’d be a discrepancy is when the line from$filenamecontains ERROR in other than the first pipe-delimited field. That would be counted by the script where it should not.