awk 在错误的列中打印字段

awk 在错误的列中打印字段

当我运行以下命令时,它会输出列列表,如下所示:

# rancher clusters
CURRENT   ID        STATE     NAME                           PROVIDER  
*         abcd      active    test-cluster                   Imported
          efgh      active    prod-cluster                   Imported
          xyzd      active    dev-cluster                    Imported

当我尝试打印 NAME 列时,结果中未返回 test-cluster

# rancher clusters | awk '{print $3}'
STATE
active
prod-cluster
dev-cluster

您可以看到 STATE 列的部分内容显示在打印的 NAME 列中。

当我打印第四列时,测试集群与 NAME 一起返回

# rancher clusters | awk '{print $4}'
NAME
test-cluster
Imported
Imported

为什么 awk 不从打印的确切列中返回值?什么可能导致一列中的值返回到另一列中?我的期望是,当我打印 $3 时,我将在第四列(名称)中得到所有结果。

答案1

获取$3- 但是,默认情况下,awk 在将记录分解为字段时会忽略前导和尾随空格。

您应该能够通过显式设置字段分隔符来强制它将前导空格视为空字段。

$ cat clusters | awk -F'[ \t]+' '{print $3}'
STATE
active
active
active

然而

$ cat clusters | awk '{print $3}'
STATE
active
prod-cluster
dev-cluster

答案2

awk 根据分隔符分割字符串(默认为一个或多个空格,即制表符或空格)。为了更清楚起见,这是您的数据,数据由|

CURRENT|ID|STATE|NAME|PROVIDER
*|abcd|active|test-cluster|Imported
efgh|active|prod-cluster|Imported
xyzd|active|dev-cluster|Imported

正如您在上面看到的,第一行$1是 is CURRENT$2isID等等。第二行$1是 is *$2isabcd等。但是,第三行是$1is efgh,它对应于 ID 列。由于 CURRENT 列中除了空格之外没有任何内容,因此 awk 会忽略它,因此$3显示第 3 行和第 4 行的 NAME。

您需要做的就是在将第一列发送到 awk 之前将其删除。以下命令应该可以为您完成此操作。

rancher clusters | cut -b 8- | awk '{ print $3 }'

cut上面管道中的命令将删除每行中的前 7 个字节,并将其余部分打印到 STDOUT 。这将导致awk不会因每行上不同数量的列而感到困惑。

答案3

默认情况下,awk 根据连续的空格序列将记录分隔为字段,并忽略任何前导尾随空格。由于您的第一个“字段”有时对于 awk 来说是空的,因此它不存在。鉴于此,有几种方法可以打印 NAME 列,最简单的是从记录末尾而不是开头开始对字段进行计数:

$ awk '{print $NF}' file
PROVIDER
Imported
Imported
Imported
$
$ awk '{print $(NF-1)}' file
NAME
test-cluster
prod-cluster
dev-cluster
$
$ awk '{print $(NF-2)}' file
STATE
active
active
active
$
$ awk '{print $(NF-3)}' file
ID
abcd
efgh
xyzd
$
$ awk '{print (NF>4 ? $(NF-4) : "")}' file
CURRENT
*


$

您需要对最后一个进行一些数学计算,这样当 NF 为 4 时$(NF-4)就不会$0被打印。您可以通过计算标题行中有多少个字段来计算预期的字段数,而不是硬编码 4:

$ awk 'NR==1{max=NF-1} {print (NF>max ? $(NF-max) : "")}' file
CURRENT
*


$

答案4

问题是有时rancher命令的输出每行有 5 个字段,有时有 4 个字段。

下面的 awk 单行语句将根据任何给定输入行有多少个字段(使用 awk 的内置变量NF)打印正确的字段:

$ awk 'NF==5 {print $4}; NF==4 {print $3}' clusters.txt
NAME
test-cluster
prod-cluster
dev-cluster

或者,如果您可以确定不会有空行,您可以使用:

$ awk '{print $(NF-1)}' clusters.txt 
NAME
test-cluster
prod-cluster
dev-cluster

如果有空行,您将收到如下错误消息:

awk: cmd. line:1: (FILENAME=clusters.txt FNR=5) fatal: attempt to access field -1

可以通过以下方式避免这种情况:

awk 'NF>=1 {print $(NF-1)}' clusters.txt 

相关内容