简体   繁体   English

将bash数组元素传递给awk regex内部循环

[英]passing bash array elements to awk regex inside loop

I'm trying to search through a file using awk, by looping over elements of a bash array. 我正在尝试使用awk搜索文件,循环遍历bash数组的元素。 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? 是否有可能以这种方式访问​​awk中bash数组的元素?

This is not the right way to pass a shell variable (or BASH array element) to awk. 这不是将shell变量(或BASH数组元素)传递给awk的正确方法。 Use it with -v option: -v选项一起使用:

myarray=(441 123)

for i in "${myarray[@]}'"; do
   awk -v i="$i" '$4 == i' myfile.txt > newfile.txt
done
  • -vi="$i" makes shell variable $i available inside awk as an awk variable i -vi="$i"使得awk中的shell变量$i可用作awk变量i
  • $4 == i is equivalent of {if ($4 == i) print $0} since print $0 is the default action $4 == i相当于{if ($4 == i) print $0}因为print $0是默认操作

There's no need for a bash loop; 不需要bash循环; you can do the whole thing in awk: 你可以用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. shell数组的内容作为单个字符串传递给awk,每个元素之间有一个空格。 split is used to create an awk array from the string. split用于从字符串创建awk数组。 Array a looks like this: 数组a看起来像这样:

a[1]=441; a[2]=123

The for loop creates an array b with two keys, b[441] and b[123] . for循环使用两个键b[441]b[123]创建一个数组b

Lines are printed when the 4th column matches one of the array keys. 当第4列与其中一个数组键匹配时,将打印行。

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. 您可以避免在外部循环遍历bash数组元素。 In the following, the array elements are passed at one shot to awk and accessed within awk using ARGV . 在下文中,数组元素一次传递给awk并使用ARGVawk访问。 Also, there's no reason why awk cannot write to the output file directly 此外,没有理由说awk无法直接写入输出文件

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[@]}"

you can also construct an awk regex: 你也可以构造一个awk正则表达式:

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 (ie '*', '\\', '?' etc) in any element of the array. 但是,如果在数组的任何元素中有元字符(即'*','\\','?'等),请务必小心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM