检查awk数组是否包含某个值

24
使用Perl,您可以检查一个数组是否包含某个值。
$ perl -e '@foo=(444,555,666); print 555 ~~ @foo ? "T" : "F"'
T

然而,使用awk时,这个类似的命令是检查数组索引而不是值。
$ awk 'BEGIN {split("444 555 666", foo); print 555 in foo ? "T" : "F"}'
F

我该如何使用awk检查数组是否包含特定值?

1
我相信你唯一的选择就是循环。 - Etan Reisner
4
就像Etan所说,你需要一个for循环。通过创建一个值作为键的新数组(散列),你可以实现相对灵活的结果,例如:awk 'BEGIN { split("444 555 666", foo); for(i=1; i<=length(foo); i++) bar[foo[i]]; print 555 in bar ? "T" : "F" }' - Thor
3
@Thor - 你可不可以只是使用for( i in foo ) bar[foo[i]]呢? - n0741337
3
你是对的,更短更简洁,这样就变成了:awk 'BEGIN { split("444 555 666", foo); for(i in foo) bar[foo[i]]; print 555 in bar ? "T" : "F" }' - Thor
5个回答

29

我是一个awk新手。我理解了Steven的答案,最终得到了下面这个希望更容易理解的代码片段。但还有两个微妙的问题:

  • Awk数组实际上是一个字典。它不是["value1", "value2"],而更像{0: "value1", 1: "value2"}
  • in检查的是键,没有内置的方法来检查值。

所以你需要将数组(实际上是一个字典)转换为将值作为键的字典。

BEGIN {

    split("value1 value2", valuesAsValues)
    # valuesAsValues = {0: "value1", 1: "value2"}

    for (i in valuesAsValues) valuesAsKeys[valuesAsValues[i]] = ""
    # valuesAsKeys = {"value1": "", "value2": ""}
}

# Now you can use `in`
($1 in valuesAsKeys) {print}

对于单行代码:

echo "A:B:C:D:E:F" | tr ':' '\n' | \
awk 'BEGIN{ split("A D F", parts); for (i in parts) dict[parts[i]]=""}  $1 in dict'

0

我的做法是将数据结构化,以充分利用编程语言提供的功能。

因此,我不会说:

BEGIN {split("444 555 666", foo); .... }

说:

BEGIN { bar[ "444" ] ; ... }

或者另一个建议:

BEGIN { 
  split("444 555 666", foo);
  for( i in FOO ) bar[foo[i]];
}

记住,在awk中,数组实际上是关联数组。


0
BEGIN {
  split("value1 value2 value3", valueArray)
  # valueArray is {1: "value1", 2: "value2", 3: "value2"}
}
{
  # given $1 is the value to test for
  for (i in valueArray) {
    if ( $1 == valueArray[i] ) {
      print $1
      # OR 
      print "True"
      # ...
    }
  }
}

0

gawk 'BEGIN { split("a b c d",parts); for (i in parts) dict[parts[i]]=1 } $1 in dict {print}' some.log

gawk 'BEGIN { split("a b c d",parts); for (i in parts) dict[parts[i]]=1 } $1 in dict {print}' some.log


虽然此代码可能解决问题,但包括解释它是如何解决问题的,以及为什么这样做会有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为未来的读者回答问题,而不仅仅是当前提问人。请[编辑]您的答案以添加解释并指示适用的限制和假设。 - Yunnosch

0

为了遵循一行代码的精神(参见Thamme的答案),更贴近OP的perl参考(三元运算符):

echo -e "a\nb\nc" | awk '{t[$1]}END{print (("a" in t) ? "yes":"no")}' # 输出yes,尝试使用("m" in t)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接