“awk”按列名不规则输出的值

“awk”按列名不规则输出的值

我正在编写一个 bash 脚本,它使用helm history(Kubernetes 工具)命令来获取我的版本的最后修订号。该命令的输出如下所示:

helm history release

    REVISION    UPDATED                     STATUS      CHART                       DESCRIPTION     
    1           Mon Feb 27 12:46:10 2017    SUPERSEDED  chart-solution-0.1.0-beta1  Install complete
    2           Fri Mar  3 11:40:55 2017    SUPERSEDED  chart-solution-0.1.0-beta1  Upgrade complete
    3           Fri Mar  3 11:41:02 2017    DEPLOYED    chart-solution-0.1.0-beta1  Upgrade complete

预期结果是仅返回列3中的数字(最后一个值)REVISION。我现在可以使用以下方法来做到这一点:

helm history release | awk -v col=REVISION 'NR==1{for(i=1;i<=NF;i++){if($i==col){c=i;break}} print $c} NR>1{print $c}' | tail -n 1
3

但是,“列”UPDATED是不规则的(以空格分隔的项目),并且上述命令仅在该REVISION列出现在 之前才有效UPDATED。如果在未来的版本中该helm history命令更改了列的顺序,事情可能会变得混乱。

一个简单的例子是,如果我尝试使用STATUS后面的列获取最后一个值UPDATED

helm history release | awk -v col=STATUS 'NR==1{for(i=1;i<=NF;i++){if($i==col){c=i;break}} print $c} NR>1{print $c}' | tail -n 1
Mar

REVISION即使列顺序发生变化,有没有办法获得正确的最后一个值?

答案1

要搜索的列名称是通过-col=命令行上提供的,如图所示。

该代码搜索从行首或空格开始的所述列名称,并记录直到下一列开头或行尾的范围。

有了这些信息,我们等到 eof 并从最后一行提取子字符串。

helm history release | perl -slne '$. == 1 and /(?:(?<=^)|(?<=\s))\Q$col\E(?:\s*|$)/ and ($p,$l)=($-[0],$+[0]-$-[0]); eof and print substr($_, $p, $l) =~ s/\s*$//r;' -- -col='REVISION' 
'

答案2

col='REVISION' \
   perl -lne '
       $. == 1 and /(?:^|\s)(?=$ENV{col}(?:\s|$))/g and $h=pos, next;
       /^.{$h}/g; /\G(\S+)/ and print $1;
       next;
   ' yourfile


col='REVISION' \
   perl -lne '
      $. == 1 and $h = index($_, $ENV{col}), next;
      /^.{$h}/g; /\G(\S+)/ and print $1;
   ' yourfile

REVISION在第一行,我们使用index() 当前行上的操作来计算 的位置$_。对于所有剩余的行,我们通过匹配 /^.../g 跳过这些位置。然后利用\G锚点从我们之前停下的地方开始匹配,并抓住外面的非空格\S+字符。

相关内容