【问题标题】:passing bash array elements to awk regex inside loop将bash数组元素传递给循环内的awk正则表达式
【发布时间】:2014-10-16 09:48:46
【问题描述】:

我正在尝试使用 awk 通过循环遍历 bash 数组的元素来搜索文件。这就是我目前正在做的事情

myarray[1] = 441
myarray[2] = 123

for i in "${myarray[@]}"
do
awk '{if ($4 == '"$i"') print $0}' myfile.txt > newfile.txt
done

这种方式可以在awk中访问bash数组的元素吗?

【问题讨论】:

  • 您没有访问那里的数组元素。您正在访问一个普通的 shell 变量。是的,假设您在 awk 上下文中引用该字符串(即您需要 "'"$i"'" 而不仅仅是 '"$i"'),这很好。
  • 似乎不起作用,我已将 "'"$i"'" 替换为我知道在文件中的 "441",这有效。所以我认为问题仍然在于定义循环中的元素。
  • 修复引用后,请注意awk 仍然不是“访问shell 变量”。相反,您在传递给 awk 的字符串中使用 shell 变量的值。 $i 的值在awk 命令执行之前被shell 扩展。
  • 您的扩展"${myarray[@]}'" 中的右引号之前有一个额外的单引号,这可能是您搞砸的原因。
  • 我已经删掉了多余的单引号,这不是我搞砸的原因。

标签: regex bash awk


【解决方案1】:

这不是将 shell 变量(或 BASH 数组元素)传递给 awk 的正确方法。与-v 选项一起使用:

myarray=(441 123)

for i in "${myarray[@]}'"; do
   awk -v i="$i" '$4 == i' myfile.txt > newfile.txt
done
  • -v i="$i" 使 shell 变量 $i 在 awk 中作为 awk 变量 i 可用
  • $4 == i 等效于 {if ($4 == i) print $0},因为 print $0 是默认操作

【讨论】:

  • 请注意,使用>> newfile.txt 而不是> newfile.txt,否则您只会看到最后一个 awk 命令的输出。
  • 这也不起作用。我可以用 441 替换 '$4 == i' 中的 i 并获得输出,但它无法识别 i
  • 您也可以将> newfile.txt 从awk 移动到done,这样文件就只写入一次,而不是每次写入然后附加。
  • @tclarke 需要考虑的事情 - 而不是编写一个 shell 循环,只需将整个数组内容一次传递给 awk 并让它完成其他所有事情。
  • @anubhava,我想我可以have contrived a way 来处理嵌入空间问题
【解决方案2】:

不需要 bash 循环;您可以在 awk 中完成所有操作:

my_array=(441 123)
awk -varr="${my_array[*]}" 'BEGIN{split(arr,a); for(i in a)b[a[i]]} $4 in b' file

shell 数组的内容作为单个字符串传递给 awk,每个元素之间有一个空格。 split 用于从字符串创建一个 awk 数组。数组a 如下所示:

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

for 循环创建一个数组 b,其中包含两个键 b[441] 和 b[123]。

当第 4 列与数组键之一匹配时打印行。

请记住,当数组中的元素包含空格时,这种方法会失败。

【讨论】:

    【解决方案3】:

    您可以避免在外部循环遍历 bash 数组元素。在下文中,数组元素一次性传递给awk,并在awk 内使用ARGV 访问。另外,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[@]}"
    

    【讨论】:

      【解决方案4】:

      你也可以构造一个 awk 正则表达式:

      myarray=(441 123)
      regex=$(IFS=\|;echo "^(${myarray[*]})\$")
      awk -v regex="$regex" '$4 ~ regex' myfile.txt > newfile.txt
      

      但是,如果数组的任何元素中存在元字符(即“*”、“\”、“?”等),请务必小心。

      【讨论】:

        猜你喜欢
        • 2012-07-14
        • 1970-01-01
        • 2017-09-11
        • 1970-01-01
        • 1970-01-01
        • 2018-11-10
        • 1970-01-01
        • 2014-01-10
        • 1970-01-01
        相关资源
        最近更新 更多