awk 使用时遇到的问题

awk 使用时遇到的问题

你能用 awk 或任何其他方法帮忙吗?

输入文件包含以下内容..

PROD   192.168.100.25   Unix                       Active
PROD   192.168.100.26   Unix - Server              Active
DEV    192.168.100.27   windows Gateway            Active
TEST   192.168.100.28   Unix Test Server           Not Active
PROD   192.168.100.29   windows mail gateway       Active down 
PROD   192.168.100.30   Unix                       Active down

现在尝试 awk 获取第 2 列和第 4 列,见下文

awk '{print $2  $4}' Inputfile

结果-

192.168.100.25   Active                       
192.168.100.26   -               
192.168.100.27   Gateway             
192.168.100.28   Test           
192.168.100.29   mail        
192.168.100.30   Active

预期结果-

192.168.100.25   Active                       
192.168.100.26   Active               
192.168.100.27   Active             
192.168.100.28   Not Active           
192.168.100.29   Active down        
192.168.100.30   Active down  

答案1

默认情况下,AWK 中的字段由空格分隔。它不关心有多少空白,因此像这样的文件会给出相同的结果:

PROD   192.168.100.25   Unix   Active
PROD   192.168.100.26   Unix   -        Server   Active

就其而言,这两行的第四个字段显然是Active-


现在,您的文件格式实际上可能是这样:字段由制表符分隔,并且中间只包含空格。我认为制表符在 SE 中发布后不会保留,并且您显示的间距也不完全符合 8 列宽制表符的间距,但我还是会注意到这一点。

然后,线条会更像

PROD<tab>192.168.100.26<tab>Unix - Server<tab><tab>Active

您可以告诉 AWK 使用制表符作为分隔符,如下所示:

$ awk -F '\t+' '{print $2, $4}' file.txt
192.168.100.25 Active
192.168.100.26 Active

不过,更常见的是每个字段之间有一个选项卡,这意味着它们不会与可变长度数据很好地对齐。那么你只需使用awk -F '\t'.


如果列实际上是固定宽度的,您可以使用例如cut来选择您需要的部分。不过,这可能涉及手动计算字符。

         1         2         3         4         5         6         7
1234567890123456789012345678901234567890123456789012345678901234567890
PROD   192.168.100.29   windows mail gateway       Active down 

从上面的计数来看,这可能有效:

$ cut -c8-23,52-70 file-fixed.txt
192.168.100.25  Active
192.168.100.26  Active
192.168.100.27  Active
192.168.100.28  Not Active
192.168.100.29  Active down 
192.168.100.30  Active down

至少GNU AWK也支持固定宽度字段,但我没有深入研究它。看https://www.gnu.org/software/gawk/manual/html_node/Fixed-width-data.html

答案2

首先,需要明确的是,awk 正在做您要求它做的事情。默认情况下,它将分隔字段任何空白,并且由于感兴趣的列可以包含空格字符,因此每个空格都表示 awk 的一个新字段。

当您有两个任意字符串输入时,在通过 linux 命令解析字段后,很难将它们分开column。根据我的经验,最好调用更强大的编程语言,例如 Python。我相信 Python CSV 库有工具可以推断固定宽度字段的格式。

如果您可以将最后一个字段更改为仅使用选项“Active”“Inactive”“Down”,那么您可以只使用以下内容:

awk '{ print $2 $NF }' Inputfile

$NF意思是“字段数”,相当于选择最后一个字段。

但是,数据的最后一列可能包含也可能不包含空格,这会破坏此语法。

或者,正如其他人指出的那样,如果字段是制表符分隔的,您应该能够使用:

awk -F $'\t' '{ print $2 $4 }' Inputfile

flag-F指定字段分隔符,$'\t'是制表符。

但是,如果条目是不是制表符分隔,您可能需要执行特定于此数据格式的操作。如果存在格式不同的其他输入文件,您可能仍会看到失败。

这是一个将使用任何实例的示例两个或更多空格字符作为字段分隔符:

awk -F ' {2,}' '{ print $2 $NF }' Inputfile

在本例中,我们的字段分隔符是正则表达式。它相当于“两个或多个空格字符的任何实例”。

这应该适用于您给出的示例,但如果您需要第一个或最后一个字段以外的字段,则当第 3 列包含多个空格时,您仍然可能会遇到麻烦。

答案3

要在这种情况下使用 awk,首先将“Not Active”和“Active down”中的空格替换为其他字符:

sed 's/Not Active/Not_Active/g ; s/Active down/Active_down/g' inputfile

然后使用 awk 提取第二个和最后一个字段:

awk '{print $2,$NF}'

最后恢复这些空间:

sed 's/_//g'

将所有这些放在一起,最终命令是:

sed 's/Not Active/Not_Active/g ; s/inputfile down/Active_down/g' active | awk '{print $2,$NF}' | sed 's/_/ /g'

相关内容