我正在编写一个 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+
字符。