如何修改 awk 命令来搜索和匹配文件多列中的值?

如何修改 awk 命令来搜索和匹配文件多列中的值?

我将以下脚本保存在 中bin,它用于根据定义的变量获取输出。目前,该脚本正在针对第 1 列运行并提供输出。我们如何更新此脚本,以便它可以在与第 1 列或第 2 列匹配时提供输出。

cat ~/bin/POUT

#!/bin/bash

exec awk -v arg=${1:?} '$1==arg' "${@:2}" inputfile

输入文件-:

 DEV       RETAIL          RETAILDEVNode  
TEST      RETAILTEST       RETAILTESTNode 
TEST       AUDIT            AUDITTESTNode
QA         AUDITQA         AUDITQANode
PROD       SALE            SALEPRODNode
QA         SALEQA           SALETESTNode
QA        FINANCE         FINANCEQANode
PROD      FINANCE         FINANCEPRODNode

目前正在获得预期输出-

$ POUT QA
QA         AUDITQA         AUDITQANode
QA         SALEQA           SALETESTNode
QA        FINANCE         FINANCEQANode

还想要如下输出(也在第 2 列中搜索):

$ POUT AUDITQA
QA         AUDITQA         AUDITQANode

Want output like this also (put any matching value and search in column 2 aslo) ---

$ POUT DITQ 
QA         AUDITQA         AUDITQANode

因此,无论变量中给出什么输入,它都应该在第 1 列和第 2 列中进行搜索并提供输出。

答案1

#!/bin/bash
arg="${1:?}"    # Capture argument value or fail
shift

awk -v arg="${arg//\\/\\\\}" 'index($1, arg) || index($2, arg)' "$@" inputfile

使用 shell 变量时始终用双引号引起来。 (始终如此,直到您理解为什么偶尔会有例外。在此之前始终使用双引号。)

$argshell变量对awk变量的乱赋值arg是为了undoawk的反斜杠处理。

我不明白为什么您要将剩余的命令行参数传递给awk inputfile作为持续来源提供。不过,我还是保留了它,以防万一这是故意的。

答案2

可能:

#! /bin/sh -
export ARG="${1?}"
shift
exec awk '
  BEGIN{
    field = 1
    arg = ENVIRON["ARG"] ""
  }
  $field == arg' "$@" inputfile

然后您可以调用它来在第二个字段中POUT AUDITQA field=2查找,AUDITQA同时保持 CLI 向后兼容性。

一些注意事项:

  • 如果您忘记了 bash 或 sh 中的扩展的引号,就像您的 中一样-v arg=${1?},它们将受到 split+glob 的影响。这里非常糟糕,因为这引入了任意命令执行漏洞。这实际上是给出的例子之一忘记在 bash/POSIX shell 中引用变量的安全隐患
  • 您不能使用mangles 反斜杠-v来传递任意文本-v。因此使用ENVIRON上面的方法就没有问题。
  • 请注意,由于awkfoo=bar.txt参数视为变量赋值,因此如果您的文件名包含=字符,则需要将它们传递为./foo=bar.txt而不是foo=bar.txt.
  • $fieldENVION["var"]/或通过传递的变量-v如果看起来是数字,则被视为数字字符串,并且==最终可能会进行数字比较而不是字符串比较。我们连接""toENVIRON["ARG"]以便始终将其视为字符串,因此,例如,如果使用10参数调用,则它与 10.0 或 010 或 1e1 不匹配。

相关内容