Reputation: 129
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?
Upvotes: 7
Views: 2226
Reputation: 74685
There'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.
Upvotes: 5
Reputation: 23374
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[@]}"
Upvotes: 2
Reputation: 781
you can also construct an awk regex:
myarray=(441 123)
regex=$(IFS=\|;echo "^(${myarray[*]})\$")
awk -v regex="$regex" '$4 ~ regex' myfile.txt > newfile.txt
However, do be careful if there are metacharacters (i.e. '*', '\', '?' etc) in any element of the array.
Upvotes: 0
Reputation: 785651
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 actionUpvotes: 5