243

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

/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提取字段?

4

8 回答 8

399

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

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
于 2012-08-30T19:47:35.440 回答
55

好消息!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是输出字段分隔符的默认变量,它被设置为制表符。该标志是必要的,因为没有像-F.

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


看另一个例子:

$ 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
于 2014-11-16T18:51:45.793 回答
7

另一种是使用 -F 选项,但将其传递给正则表达式以打印左右括号之间的文本()

文件内容:

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

于 2020-06-18T09:09:08.550 回答
6

如果您的空格是一致的,您可以将其用作分隔符,而不是\t直接插入,您可以设置输出分隔符,它将自动包含在内:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'
于 2012-08-30T19:51:09.520 回答
5

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

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

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

于 2015-03-22T13:50:26.627 回答
3

Perl 单行:

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

使用这些命令行选项:

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

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

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

  • -Fautosplit 修饰符,在此示例中拆分为/=

  • -e执行 perl 代码

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

于 2015-09-09T16:58:19.507 回答
0

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

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

于 2015-02-25T14:38:57.163 回答
0

使用 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(逐行,非自动打印)命令行标志逐行输入。行split位于正则表达式上,该正则表达式由使用运算符创建的自定义字符类 ( /=)组成<[ ]>。元素[2,4,7]然后put给出上面的结果。

当然,上面是一个“简单”的实现,并且 Raku 是 Perl 系列语言,TMTOWTDI 适用。因此,行可以位于由“OR”运算符split分隔的文字字符上。|元素编号(在 Perl 和 Raku 中都是零索引)可以在例程中添加:skip-empty副词来收紧。split空白可以trim从每个元素中删除(使用map),并且所需的元素(现在[1,3,6]join使用\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

于 2021-11-23T19:06:55.877 回答