awk NR variable not working as expected, getting the whole line while asking for first field
echo cat:
cat Records.txt
echo ""
echo Using a digit for the second record:
record_id=$(awk 'NR==2{print $1; exit}' Records.txt)
echo $record_id
echo ""
a=2
echo a is set to $a
echo ""
echo Using a variable and single quotes:
record_id=$(awk 'NR==$a{print $1; exit}' Records.txt)
echo $record_id
echo Using a variable and double quotes:
record_id=$(awk "NR==$a{print $1; exit}" Records.txt)
echo $record_id
Output
cat:
Apples 1000 happy worms
Carrots 10 happy bunnies
Using a digit for the second record:
Carrots
a is set to 2
Using a variable and single quotes:
Using a variable and double quotes:
Carrots 10 happy bunnies
I understand that double quotes are needed to use a variable, but why is it nolonger confined to output of the first field only? I only want the word Carrots.
Solution 1:
When you use single quotes, $a
is not expanded by the shell, so awk sees literal NR=$a
. Since the awk variable a
is uninitialized, that is equivalent to NR=$0
which compares the current record number to the value of the record.
When you use double quotes, both $a
and $1
are expanded by the shell, and the expression becomes NR==2{print ; exit}
because $1
is empty in your interactive shell - that's why it prints the whole record.
Here are a couple of ways to pass shell variable values to awk while avoiding the trickiness of shell expansion:
awk -v a="$a" 'NR==a{print $1; exit}'
or
export a
awk 'NR==ENVIRON["a"]{print $1; exit}'
(You could use double quotes to allow expansion of $a
and then prevent expansion of $1
by additional quoting/escaping ex. awk "NR==$a{print \$1; exit}" Records.txt
but I recommend against it.)