使用字符串变量在AWK中打印列

3

我正在尝试在我的AWK(或GAWK)程序中使用一个变量来打印多列。

我从命令行中获取要打印的列:

gawk -v cols=1,2,3 -f sample.awk -F,

我希望能够在我的 BEGIN{} 块中设置此变量,并在程序的主体部分使用它。
BEGIN{
  split(cols, col_arr, FS)

  i=1;
  col_str = "$"col_arr[1];
  for(col in col_arr){
    if (i > 1){ 
      col_str = col_str",$"col;
    }
    i++;
  } 
}

{
  print col_str
}

然而,这只会打印 "$1,$2,$3"。我该如何更改以打印第 1、2 和 3 列?


1
如果您在BEGIN块中执行此操作,它将无法正常工作。 - Avinash Raj
3个回答

1
你最好使用一个程序(比如awk)来编写最终运行的awk脚本。
例如:
trap "rm -f script.awk; exit 1" 0 1 2 3 13 15

awk '{ printf "{ print ";
       pad = ""; for (i = 1; i <= NF; i++) { printf "%s$%d", pad, $i; pad = ", " }
       print " }"
     }' <<< "1 2 5" > script.awk

awk -f script.awk data.file

rm -f script.awk
trap 0

要打印的列被显示为一个here字符串,这是Bash的一个特性,但可以来自文件或其他所需来源。trap命令是shell脚本,确保临时文件script.awk被删除。如果脚本同时运行,嵌入进程ID到名称中可能更好以确保唯一性。如果您真的很担心,使用mktemp或类似程序创建一个更难猜测的名称。没有要求脚本文件以awk结尾;如果你发现它乱七八糟的,只是让它清晰地表明它包含了什么。

1

BEGIN规则只执行一次,在读取第一个输入记录之前。

试试这个

awk '{cols = $1 OFS $2 OFS $5; print cols}' file

更新

要么你需要生成像Jonathan Leffler展示的脚本,因为与shell(和PERL)不同,AWK不会在字符串中评估变量,或者你可以使用类似下面的方法。

BEGIN{
       sub(/,$/,"",cols)
       n=split(cols,C,/,/)
}
function _get_cols(i,s){
       for(i=1;i<=n;i++) s = length(s) ? s OFS $(C[i]) : $(C[i])
       return s  
}
{
     print _get_cols()
}

Execute

awk -v cols=2,3, -f test.awk infile

否则,你就要尝试类似这样的东西。
#!/bin/bash

# Usage : _parse <FS> <OFS> 1 2 3 ... n < file
_parse()
{
    local fs="$1"
    local ofs="$2"
    shift 2
    local _s=
    local f

    for f; do
        _s="${_s}\$${f},"
    done
    awk -F"$fs" -v OFS="$ofs" "{ print ${_s%,} }"
}

# Call function
_parse ' ' '\t' 1 3 < infile

我将从一个数组中获取要打印的列,并希望仅定义要打印的值一次,而不是不断循环包含要打印的列号的数组。我只是试图保持示例简单。 - DJElbow
谢谢提供这些示例。我可能会最终采用类似的解决方案。 - DJElbow

0

以下是如何在不使用循环或数组的情况下完成它:

jot -s '' -c - 65 126 | 
mawk -f <( mawk -v __='3,59,8,42,17,39' '
           BEGIN { 
               OFS =(FS = ",")"$"
             $(ORS = _) = __
             
          print "{ print $" ($!(NF=NF) ) " } " }' ) FS= OFS='\f'
C
 {
  H
   j
    Q
     g

在子进程awk调用中发生的是通过即时生成代码来硬编码所需的列。
# gawk profile, created Mon Jan 16 18:27:35 2023

# Rule(s)

 1  {
 1      print $3, $59, $8, $42, $17, $39
}

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