I'm trying to search through a file using awk, by looping over elements of a bash array. This is what I'm currently doing
myarray[1] = 441
myarray[2] = 123
for i in "${myarray[@]}"
do
awk '{if ($4 == '"$i"') print $0}' myfile.txt > newfile.txt
done
Is it possible to access elements of a bash array in awk in this way?
This is not the right way to pass a shell variable (or BASH array element) to awk. Use it with -v
option:
myarray=(441 123)
for i in "${myarray[@]}'"; do
awk -v i="$i" '$4 == i' myfile.txt > newfile.txt
done
-v i="$i"
makes shell variable $i
available inside awk
as an awk variable i
$4 == i
is equivalent of {if ($4 == i) print $0}
since print $0
is the default actionThere's no need for a bash loop; you can do the whole thing in awk:
my_array=(441 123)
awk -varr="${my_array[*]}" 'BEGIN{split(arr,a); for(i in a)b[a[i]]} $4 in b' file
The contents of the shell array are passed to awk as a single string, with a space in between each element. split
is used to create an awk array from the string. Array a
looks like this:
a[1]=441; a[2]=123
The for
loop creates an array b
with two keys, b[441]
and b[123]
.
Lines are printed when the 4th column matches one of the array keys.
Bear in mind that this approach fails when the elements in the array contain spaces.
You can avoid looping through the bash
array elements externally. In the following, the array elements are passed at one shot to awk
and accessed within awk
using ARGV
. Also, there's no reason why awk
cannot write to the output file directly
awk -v len="${#myarray[@]}" '
BEGIN{t=ARGC; ARGC-=len; for(i=2; i<t; ++i) b[ARGV[i]]++ };
$4 in b { print > "newfile.txt"}' myfile.txt "${myarray[@]}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With