AWK:将 shell 变量传递给 awk

AWK:将 shell 变量传递给 awk

我正在尝试通过多变的从 shell 脚本到表的模式识别子集的参数数量。到目前为止,这是我的尝试:

文件“infile”:

    ID,GROUP
    1,GROUP2    
    2,GROUP2    
    3,GROUP4    
    4,GROUP4    
    5,GROUP5    
    6,GROUP5    
    7,GROUP23   
    8,GROUP23   
    9,GROUP23   

文件subset.sh:

    #!/bin/sh
    rm -f outfile_$week

    week = $1
    shift

    for TOKEN in "$@"
    do

    echo "adding records for" $TOKEN

    awk -F "," -v group = $TOKEN '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile >> outfile_$week
    done

我还尝试过 group = "$TOKEN", "group = $TOKEN" ,然后都用单引号。我这样提交:

    sh subset.sh 061314 GROUP2 GROUP23

我得到的错误信息非常少

    Usage: awk [-F fs][-v Assignment][-f Progfile|Program][Assignment|File] ...

非常感谢任何帮助,谢谢!

编辑:我尝试跑步

    awk -F "," -v group ="GROUP1" '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile

无济于事...(与上面相同的错误)有人知道这可能发生的任何原因吗?

答案1

你应该写:

-v group="$TOKEN"

而不是-v group = $TOKEN,这会导致 中的语法错误awk

答案2

听起来像你想要的:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 && $2 in group' "$@" < infile

或者,如果您确实想将参数视为正则表达式来匹配第二列:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 {
    for (i in group) if ($2 ~ i) {print; next}
  }' "$@" < infile

答案3

您面临的直接问题是等号周围的空格。该选项的参数-v应该是一个赋值。 awk 看到 的参数-v,后跟脚本 ( =),然后是文件名( 的值TOKEN、您的脚本和您的文件名)。

您在 shell 脚本中犯了类似的错误:week = $1应该是week="$1"

顺便一提,总是在命令替换两边加上双引号。例如,如果TOKENis *,它将被当前目录中的文件列表替换。

awk -v "group=$TOKEN"

不过,这不会设置group为 的值TOKEN,因为 awk 将赋值的右侧视为 awk 语法中的文字。例如,如果 的值TOKEN是 7 个字符的字符串foo\bar,则 awk 变量group将设置为 6 个字符的字符串foo␈ar,其中是退格字符(字节值 8)。

将变量传递给 awk 脚本的直接方法是将其导出到环境中,并通过数组使用它ENVIRON

此外,您没有group在 awk 脚本中的任何地方使用该变量。正则表达式/group/匹配包含 5 个字符的 string 的任何字符串group。如果您想检查该字段是否恰好等于 的值group(例如,如果 的值TOKENGROUP2则包含的字段GROUP24将不会匹配),请使用相等运算符==

  export TOKEN
  awk -F "," '{ if (FNR > 2 && $2 == ENVIRON["TOKEN"]){print $0} }' infile >> outfile_$week

这是整个脚本,进一步简化为使用 awk 的条件动作语法(这里省略了动作,因为这print $0是默认的)并避免每次都打开输出文件:

#!/bin/sh
week="$1"
shift
for TOKEN in "$@"
do
  echo "adding records for" $TOKEN
  awk -F "," 'FNR > 2 && $2 == ENVIRON["TOKEN"]' infile 
done >"outfile_$week"

斯特凡·查泽拉斯的回答使用 awk 的更高级方法不需要多次处理输入文件。

相关内容