【问题标题】:awk regex extracting part of urlawk 正则表达式提取部分 url
【发布时间】:2026-01-14 04:45:01
【问题描述】:

我对 awk 很陌生。我有多个文件包含类似于

的行
xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin
abc msg=(1448783938.658:149777):   uid=506   comm="abc.py"   exe="/install/bio/toolx/bin
abc msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/bio/tooly/bin

我需要两个输出。 一个。一个文件只包含所有文件中的 uid 和 exe 列(就在 /install/ 之后) 例如

505 python
506 bio
505 bio

我可以用

打印 exe
awk -F '/' '{ print $3}'

但不确定如何使用它打印 uid。

  1. 一个包含 uid 和 exe 列的文件仅包含 /bio/ 后面的字符串 例如

    506 工具x

    505工具

任何帮助表示赞赏。

【问题讨论】:

    标签: regex awk


    【解决方案1】:

    您可以使用以下awk 命令:

    awk -F'[[:space:]="/]+' '{print $5, $10}' file
    

    我正在使用一组分隔符。这使得访问感兴趣的值变得简单。但是,它仅在路径不包含 <space>="/ 时才有效。

    顺便说一句,sed 也可以用于此目的,因为没有使用分隔符,所以无论路径中的任何类型的字符都可以使用:

    sed -r 's~.*uid=([^[:space:]]+).*exe="/install/([^/]+).*~\1 \2~' file
    

    【讨论】:

      【解决方案2】:

      类似awk解决方案

      $ awk -F" +|[=/]" '{print $5,$11}' bio
      505 python
      506 bio
      505 bio
      

      【讨论】:

      • 请注意,* 在字符类中使用时没有特殊含义。这只是一个文字*。如果你考虑到这一点,你的答案和我的一样。
      【解决方案3】:

      我会保持简单并使用默认字段分隔符——然后使用 subsplit 清理每个字段以进行打印。这是拆分解决方案。

      awk '{ split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'
      

      这是如何开发的:

      $ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ print $3, $5 }'
      uid=505 exe="/install/python/bin
      $ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ split($3, uid, "="); print uid[2], $5 }'
      505 exe="/install/python/bin
      $ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'
      505 python
      

      我首先尝试了一个基于 sub 的解决方案,但结果证明它比基于 split 的解决方案更长更神秘——split em> 解决方案似乎更简单。 (在需要基于 sub 的解决方案的情况下,也许 sed 会是更好的候选语言。)

      应该添加一些过滤器,以确保我们只处理有效行,它可以像下面这样简单:

      awk '$3 ~ /uid=/ && $5 ~ /exe="\/install\// { split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'
      

      另一件事...如果 uid 和 exe 字段在您的文件中逐列移动,您将不得不使用 for 循环来寻找它们...以下:

      #! /usr/bin/awk -f
      {
              u=0
              e=0
              for (i=1; i<=NF; i++) {
                      if ($i ~ /uid=/)
                              u=i
                      else if ($i ~ /exe="\/install\//)
                              e=i
                      if (u && e)
                              break
              }
              if (!u || !e)
                      next
              split($u, uid,"=")
              split($e, exe, "/")
              print uid[2], exe[3]
      }
      

      在这种情况下,我们在前面的示例中放入的用于检查有效性的主要模式嵌入在 for 循环中。

      【讨论】: