【问题标题】:Using multiple delimiters in awk在 awk 中使用多个分隔符
【发布时间】:2012-08-25 14:43:07
【问题描述】:

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

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

【问题讨论】:

  • 为了回答我相同但不同的问题,awk 在字段为空白时正在吞噬字段,这会限制字段编号。我将-F " " 更改为-F "[ ]" 并且awk 不再吞下空白字段。

标签: awk command-line text-processing


【解决方案1】:

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

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

【讨论】:

  • 当然,cat 进程不是必需的:awk '...' file。此外,使用输出字段分隔符会更整洁:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
  • Awk 分隔符可以是正则表达式...这让我很开心!
  • @das.cyklone: awk 也可以有多个分隔符,| :例如:awk -F 'this|that|[=/]' '......' (用于分隔事物的单词/字符串)(请注意,这会保留字段中的空格在 2 个分隔符之间。也添加 |[ \t]+ 可能很有用,但会使事情变得棘手......因为“this”之前和之后经常有空格,这将使空格和“之间”出现 2 个额外的空字段这')
  • 我在 2 个不同的发行版上尝试过这个,我得到了相同的行为:我想从 netstat -ntpl "netstat -ntpl |sed 's/:/ /' |awk ' {print $5}'" 有效,但无需双管道也可以这有效,但我没想到字段 17 上的数据:"netstat -ntpl |awk -F" |:" '{print $17}'"
  • 是的...这让我得到了我想要的:awk -F"[ :]+" '/\/postmaster *$/ {print $5}'
【解决方案2】:

好消息! 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 这样的 OFS 内置。

  • {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

【讨论】:

    【解决方案3】:

    另一种方法是使用 -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

    【讨论】:

    • 您的答案出现在删除队列中,因为 10 次中有 9 次,链接到自己博客的信誉为 1 的用户通常是垃圾邮件。但你的例外是规则。过去 10 年的内容有一座金矿,希望你有计划让它永垂不朽。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

        【解决方案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 开始。

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

          • print $3 " " $5 " " $7 可以像print $3, $5, $7 一样打印。另外,我看不到使用 awk 然后通过管道连接到 sed 的优势。一般来说,awk 就足够了,其他人的回答表明了这一点。
          【解决方案8】:

          使用 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,它由使用&lt;[]&gt; 运算符创建的自定义字符类(/=) 组成。元素 [2,4,7] 然后是 put 以给出上述结果。

          当然,以上是“基本”实现,Raku 是 Perl 系列语言,适用 TMTOWTDI。所以行可以是 split 在由 | "OR" 运算符分隔的文字字符上。元素编号(在 Perl 和 Raku 中都是零索引)可以通过将 :skip-empty 副词添加到 split 例程来加强。空白可以是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

          【讨论】:

            猜你喜欢
            • 2018-04-08
            • 2014-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-06
            • 2017-12-02
            相关资源
            最近更新 更多