在awk中使用多个分隔符

我有一个文件,其中包含以下行:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

在上面的输出中,我想提取3个字段(数字2,4和最后一个*.example.com)。我得到以下输出:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

我如何也提取域名后的最后一个字段'='?我如何使用multiple delimiter提取字段?

517281 次浏览

分隔符可以是正则表达式。

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

生产:

tc0001   tomcat7.1    demo.example.com
tc0001   tomcat7.2    quest.example.com
tc0001   tomcat7.5    www.example.com

如果你的空格是一致的,你可以使用它作为分隔符,也不是直接插入\t,你可以设置输出分隔符,它将自动包含:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'

好消息!awk字段分隔符可以是正则表达式。你只需要使用-F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

返回:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

在这里:

  • -F"/|="将输入字段分隔符设置为/=

  • -vOFS='\t'使用-v标志来设置变量。OFS是输出字段分隔符的默认变量,它被设置为制表符。这个标志是必要的,因为OFS没有像-F这样的内置标志。

  • {print $3, $5, $NF}根据输入字段分隔符打印第3、5和最后一个字段。


请看另一个例子:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

这个文件有两个字段分隔符,#_。如果我们想打印第二个字段,而不管分隔符是一个还是另一个,让我们让两个都是分隔符!

$ awk -F"#|_" '{print $2}' file
how
am

其中文件编号如下:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
1    2   3   4            1  2   3    4    5    6

我看到黑板上有很多完美的答案,但我仍然想上传我的代码,

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'

对于任意数字25的字段分隔符或字母a#或空格,其中分隔字符必须至少重复2次,不超过6次,例如:

awk -F'[2-5a# ]{2,6}' ...

我确信使用()和参数存在这种变化

Perl一行程序:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

使用以下命令行选项:

  • -n循环输入文件的每一行,将行放入$_变量中,不自动打印每一行

  • -l在处理之前删除换行符,并在处理之后将它们添加回来

  • -a自动拆分模式- perl将自动将输入行拆分到@F数组中。默认为空格分割

  • -F自动分割修饰符,在本例中,它在/=上进行分割

  • -e执行perl代码

Perl与awk密切相关,然而,@F自动拆分数组从索引$F[0]开始,而awk字段以$1开始。

另一种方法是使用-F选项,但将其传递给regex来打印左括号和右括号()之间的文本。

文件内容:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

命令:

awk -F"[()]" '{print $2}' filename

结果:

smbw
smbt
smbn
smbs

使用awk打印[]之间的文本:

使用awk -F'[][]',但awk -F'[[]]'将不起作用。

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html

使用Raku(以前称为Perl_6)

raku -ne '.split(/ <[/=]> /).[2,4,7].put;'

样例输入:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

样例输出:

tc0001 tomcat7.1  demo.example.com
tc0001 tomcat7.2  quest.example.com
tc0001 tomcat7.5  www.example.com

上面是一个用Raku编写的解决方案,Raku是perl编程语言家族的一个成员。简单地说,用-ne(按行,非自动打印)命令行标记在read中按行输入。行是正则表达式上的split,该正则表达式由用<[ ]>操作符创建的自定义字符类(/=)组成。元素[2,4,7]然后put给出上述结果。

当然,上面是一个“基本的”实现,Raku是一种perl家族语言,因此可以应用TMTOWTDI。所以行可以是由| "或"分隔的文字字符上的split;操作符。元素编号(在Perl和Raku中都是零索引)可以通过在split例程中添加:skip-empty副词来加强。空格可以从每个元素中trim-med(使用map),所需的元素(现在是[1,3,6])被join-ed,使用\t制表符,得到以下结果:

raku -ne '.split(/ "/" | "=" /, :skip-empty).map(*.trim).[1,3,6].join("\t").put;' file
tc0001  tomcat7.1   demo.example.com
tc0001  tomcat7.2   quest.example.com
tc0001  tomcat7.5   www.example.com

https://raku.org