awk with if statements

I am trying to print from a file using awk, but my output is empty.
Here is my code so far

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts
done < Accounts

I have also tried this:

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            echo $LINE  | awk -F',' '{ if($1==accountNum) { print $3.$2 } }' 
done < Accounts

The input file is :

1,Doe,John
2,Rooney,Wayne
3,Smith,Will
4,Crow,Russel
5,Cruise,Tom

The expected output when I run the file is

$./file.sh 3
Will Smith

But I get the following

$./file.sh 3
$

That is nothing is being printed out. I know the solution with cut, but I want to use awk.

Asked By: gkmohit

||

You have:

accountNum=$1
awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts

How does the shell variable accountNum get into awk? It doesn’t: you need to provide its value to awk explicitly. You can use:

awk -F',' '{ if($1=='"$accountNum"') { print $3.$2 } }' Accounts

which leaves single quotes and has the shell substitute the value of its variable into the awk command, then reenters single quotes for the rest of the command string.

A better or at least more idiomatic script would be:

#!/bin/sh
accountNum=$1
awk -F, '$1 == "'"$accountNum"'" { print $3,$2 }' Accounts

which deals with non-numeric account numbers (quoting the substituted variable), uses a pattern block instead of an explicit if (the {} block will run if the test before it is true), and prints a space between the names as you wanted (because of ,). If you prefer to use if explicitly, move the test inside your existing if statement.

Depending on your real goal awk may not be the best fit for what you’re doing. The above still fails if the script’s $1 has quotes in it. The shell loop you had wasn’t doing anything useful, although it would have repeated the output many times.

Answered By: Michael Homer

Your script already practically does the job without any awk at all:

while IFS=, read -r num last first
    do  [ $((num==accountNum)) -eq 1 ] && 
        printf '%s.%sn' "$first" "$last"
done < Accounts

I’m not suggesting that this is a better or more efficient solution than using awk alone, but if you want the while...read loop, this certainly beats separate awk processes per each line. Just an FYI, I guess.

Answered By: mikeserv

You should use -v option of awk:

awk -F',' -v accNum="$1" '$1 == accNum {print $3,$2}'

With $1 in double quote, the shell will handle all its special character ( if has ) for you.

Answered By: cuonglm
#!/bin/bash

awk -v a="$1" -F ',' '$1 == a { print $3, $2 }' Accounts

With -v a="$1" we set the awk variable a to the value of the script’s first command line argument, then we specify that the input is comma separated with -F ','. If the first column is equal to the value of a, print the two other columns in reverse order.

You get nothing in your output as you are comparing the first column to the awk variable accountNum, which is unset.

Had there been an entry whose first column had 0 (zero) in it, that entry would have been printed. This is because the value of unset variables in awk evaluates to zero.

Answered By: Kusalananda
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.