awk: cmd. line:1: { print \$9} : syntax error - shell

I am trying to run the following command to get the "gis" & "cpu" usage from shell script. However when i try to run this command even manually, then i am getting the below error.
Any senior/expert please help on this.
$ top -b | head -n 8 | grep -w gis | awk '{ print \$9}'
awk: cmd. line:1: { print \$9}
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: { print \$9}
awk: cmd. line:1: ^ syntax error
$ top -b | head -n 8 | grep -w gis | awk '{ print \$10}'
# Same error i am getting for second command as well.

You don't need to escape the $. You are using single quotes, so the shell won't interpolate the $9. If you were using double quotes, you would need to escape it.
So, you have to...
top -b | head -n 8 | grep -w gis | awk '{ print $9}'
or
top -b | head -n 8 | grep -w gis | awk "{ print \$9}"

Related

Assign and storing the varible of total number of lines of a file to use in the next command in shell & awk script

Please let me know the mistake in the following command
for i in file*; do printf "$i processing" && \
for j in {3..10}; do printf ">=$j\t" && k=$(< "$i" wc -l) ; \
awk 'BEGIN {FS="\t"} {if ($7 >= '$j') {print $0} }' $i| \
awk 'END{print (NR/"$k")*100}' ; done ; done
file1 processong
>=3 awk: cmd. line:1: (FILENAME=- FNR=126052) fatal: division by zero attempted
>=4 awk: cmd. line:1: (FILENAME=- FNR=118562) fatal: division by zero attempted
>=5 awk: cmd. line:1: (FILENAME=- FNR=113376) fatal: division by zero attempted
>=6 awk: cmd. line:1: (FILENAME=- FNR=109501) fatal: division by zero attempted
>=7 awk: cmd. line:1: (FILENAME=- FNR=106388) fatal: division by zero attempted
>=8 awk: cmd. line:1: (FILENAME=- FNR=103781) fatal: division by zero attempted
>=9 awk: cmd. line:1: (FILENAME=- FNR=101547) fatal: division by zero attempted
>=10 awk: cmd. line:1: (FILENAME=- FNR=99552) fatal: division by zero attempted
Thanks
The reason you obtain division by zero is due to the following line:
awk 'END{print (NR/"$k")*100}'
You attempt to use a shell variable $k which you assigned as k=$(< "$i" wc -l). However, you use it in a single quoted string, so bash does not perform the variable substitution as you imagine. It only does this in double-quoted strings. More details here: How do I use shell variables in an awk script?
So your mystery line should look like:
for i in file*; do
printf "$i processing" && \
for j in {3..10}; do
printf ">=$j\t" && k=$(< "$i" wc -l)
awk -v j="$j" 'BEGIN {FS="\t"} {if ($7 >= j) {print $0} }' $i \
| awk -v k="$k" 'END{print (NR/k)*100}'
done
done
However, this command can be cleaned up a lot:
no need for compound commands using &&. (printf will not fail)
Don't use printf "string", but rather printf -- "%s" "string"
when using awk, you are not in need of anything of the form like grep, wc, sed, ...
for i in file*; do
printf -- "%s" "$i processing"
for j in {3..10}; do
printf -- "%s" ">=$j\t"
awk -v j="$j" 'BEGIN {FS="\t"}($7>j) { print; c++ }END{print (c/NR)*100}' "$i"
done
done
Using GNU awk, you can even reduce this entire code-block into a single-awk, but this is beyond the scope of this question.

awk: cmd. line:1: (FILENAME=- FNR=1) fatal: attempt to access field -1

I have a code sample that does not work at all. I permanently get an error produced by awk.
queried_num=$(echo -e "$domains"|awk '{print $(NF-1)}'|awk -F. '{print $(NF-2) "." $(NF-1)}'|wc -l)
queried_domain=$(echo -e "$domains"|awk '{print $(NF-1)}'|awk -F. '{print $(NF-2) "." $(NF-1)}'|uniq)
I don't really know what's going wrong and how to fix it.
The error is: awk: cmd. line:1: (FILENAME=- FNR=1) fatal: attempt to access field -1
The 2 scripts you posted:
queried_num=$(echo -e "$domains"|awk '{print $(NF-1)}'|awk -F. '{print $(NF-2) "." $(NF-1)}'|wc -l)
queried_domain=$(echo -e "$domains"|awk '{print $(NF-1)}'|awk -F. '{print $(NF-2) "." $(NF-1)}'|uniq)
could be written as just something like:
queried_num=$(echo -e "$domains"|wc -l)
queried_domain=$(echo -e "$domains"|awk '{n=split($(NF-1),f,/./); $0=f[n-2] "." f[n-1]} !seen[$0]++')
and then to discard empty lines (which would cause the problem you describe) would be:
queried_num=$(echo -e "$domains"|grep '.'|wc -l)
queried_domain=$(echo -e "$domains"|awk '!NF{next} {n=split($(NF-1),f,/./); $0=f[n-2] "." f[n-1]} !seen[$0]++')
If that's not what you're looking for then edit your question to include some concise, testable sample input and expected output so we can help you.

error in awk of shell script

I am getting the below error ith my code.What is missing in it? My goal is to print 13.0.5.8 in $version
#!/bin/ksh
file="abc_def_APP_13.0.5.8"
if echo "$file" | grep -E "abc_def_APP"; then
echo "Version found: $file"
version1=(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)
version2=(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)
echo $version1
echo $version2
version=$version$version2
echo $version
else
echo "Version not found"
fi
Please find below the error:
./version.sh: line 7: syntax error near unexpected token `|'
./version.sh: line 7: ` version1=(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)'
./version.sh: line 9: syntax error near unexpected token `|'
./version.sh: line 9: ` version2=(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)'
./version.sh: line 18: syntax error near unexpected token `else'
There's no need for awk at all. Just trim every character before the last underscore, like so:
file="abc_def_APP_13.0.5.8"
version="${file##*_}"
echo "$version"
See http://mywiki.wooledge.org/BashFAQ/073 for documentation on this technique, or see "parameter expansion" in bash's own docs.
To treat the last segment separately is also straightforward:
file="abc_def_APP_13.0.5.8"
version="${file##*_}" # result: 13.0.5.8
version_end="${version##*.}" # result: 8
version_start="${version%.*}" # result: 13.0.5
echo "${version_start}/${version_end}" # result: 13.0.5/8
Because this happens internally to bash, without executing any external commands (such as awk), it should be considerably faster to execute than other approaches given.
The problem is your backticks are missing $ you need to fix the following two lines like so:
version1=$(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)
version2=$(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)
This will fix the syntactical errors. The following line doesn't make much sense as $version hasn't been initialize yet:
version=$version$version2
Did you mean:
version="${version1}.${version2}"
A side note you are using the -E option with grep but you aren't using any extended regexp features, in fact you are doing a fixed string string search so -F is more appropriate. You probably also want to use the -q option to suppress the output from grep.
Personally I would do:
file="abc_def_APP_13.0.5.8"
echo "$file" | awk '/abc_def_APP/{print "Version found: "$0;
print $4,$5,$6;
print $7;
print $4,$5,$6,$7;
next}
{print "Version not found"}' FS='[_.]' OFS=.
If you just want the version number in the variable version then why not simply:
version=$(echo "$file" | grep -o '[0-9].*')
It can all be done in a single awk command and without additional cut command. Consider following command:
read version1 version2 < <(echo $file|awk -F "[_.]" '{
printf("%s.%s.%s ", $4, $5, $6); printf("%s", $7);
for (i=8; i<=NF; i++) printf(".%s", $i); print ""}')
echo "$version1 :: $version2"
OUTPUT
13.0.5 :: 8

CSV Column Counts via Command Line Alias

I have a Bash scripting question that's no longer important to me but has still been driving me crazy because I can't figure it out.
I was trying to compare column counts of CSV files via the command line, and found some instructions here that looked promising. The original command worked perfectly, but every attempt to create an alias failed.
Original command line - WORKS!
head -n 1 FILENAME.CSV | awk '{split($0, pieces, ","); for (i=1; i<=length(pieces); i++) print pieces[i];}' | wc -l
Ex. molsen#molsen-M14xR2:~/projects/ee-export$ head -n 1 ee-content.csv | awk '{split($0, pieces, ","); for (i=1; i<=length(pieces); i++) print pieces[i];}' | wc -l
7
Aliased command line - FAILS!
alias csvcc="head -n 1 $1 | awk '{split($0, pieces, ","); for (i=1; i<=length(pieces); i++) print pieces[i];}' | wc -l"
Ex. molsen#molsen-M14xR2:~/projects/ee-export$ csvcc ee-content.csv
awk: cmd. line:1: {split(bash, pieces, ,); for (i=1; i<=length(pieces); i++) print pieces[i];}
awk: cmd. line:1: ^ syntax error
awk: cmd. line:1: {split(bash, pieces, ,); for (i=1; i<=length(pieces); i++) print pieces[i];}
awk: cmd. line:1: ^ syntax error
awk: cmd. line:1: {split(bash, pieces, ,); for (i=1; i<=length(pieces); i++) print pieces[i];}
awk: cmd. line:1: ^ 0 is invalid as number of arguments for split
1023 ee-content.csv
I've tried all sorts of variations on this command with different quoting and escaping, but they all produce errors. I even looked into strong vs. weak quoting, but didn't find anything useful. Also, I came up with this simpler command, but it fails in the same way:
COMMAND LINE USING SED - WORKS!
head -n 1 file.csv | sed 's/\,/\n/g' | wc -l
molsen#molsen-M14xR2:~/projects/ee-export$ head -n 1 ee-content.csv | sed 's/\,/\n/g' | wc -l
7
ALIAS USING SED - FAILS (COUNTS LINES, NOT COLUMNS)
alias csvcc="head -n 1 $1 | sed 's/\,/\n/g' | wc -l"
molsen#molsen-M14xR2:~/projects/ee-export$ csvcc ee-content.csv
1023 ee-content.csv
Can anyone can tell me what I'm missing here? Thanks for your help!
rzymek's Solution 1 doesn't work because csvcc <ee-content.csv expands to
head -n 1 | sed 's/\,/\n/g' | wc -l <ee-content.csv
i. e., the input file is not fed to head, but to wc -l; this explains why it gives the line count.
Another solution with alias and awk:
alias csvcc="awk -F, 'NR==1 { print NF }'"
Aliases don't use $1, scripts do.
Solution 1.
alias csvcc="head -n 1 | sed 's/\,/\n/g' | wc -l"
^--- no $1, input will be read from stdin
Usage:
csvcs < ee-content.csv
Solution 2.
Put the line in a bash script file in $HOME/bin/csvcc:
#!/bin/bash
head -n 1 | sed 's/\,/\n/g' | wc -l
Then make the script executable:
chmod +x ~/bin/csvcc
On ubuntu $HOME/bin is added to $PATH by default. If it's not on your system, than add this line to your ~/.profile:
export PATH="$HOME/bin:$PATH"
Usage:
csvcs ee-content.csv

Eval awk command with single quotes

I have a function "checkExist" that takes in a command and executes it based on whether or not the output file already exists. I pass a command like this, where file1 and file2 are just the names of output files that the commands create, so if they already exist it will ask if you want to overwrite, else it will skip:
checkExist file1 file2 command1 command2
In actual use like this:
checkExist 1.txt 2.txt "echo $1 | awk '$5 <= 10 {print $3, $4}'" "echo $2 | awk '$5 <= 10 {print $3, $4}'"
$1 and $2 above are inputs to the script "smartfilter.sh" containing the function checkExist within. So they are just file inputs.
Later in the checkExist function if the user types 'Y/y' to overwrite, or the files don't already exist then it will
eval $3 &
eval $4 &
wait
And I get an error like so:
awk: >= 10 {print , }
awk: ^ syntax error
awk: >= 10 {print , }
awk: ^ syntax error
awk: >= 10 {print , }
awk: ^ syntax error
awk: cmd. line:1: >= 10 {print , }
awk: cmd. line:1: ^ unexpected newline or end of string
I know it is to do with the single quotations ' around the awk and eval not parsing them correctly. I have tried \' but that doesn't work either. Is there a proper way to do this?
checkExist 1.txt 2.txt "echo $1 | awk '\$5 <= 10 {print \$3, \$4}'" "echo $2 | awk '\$5 <= 10 {print \$3, \$4}'"

Resources