【问题标题】:Extract string under a string from a file in linux从linux中的文件中提取字符串下的字符串
【发布时间】:2016-04-28 11:01:02
【问题描述】:

这个网站过去帮了我很多,但现在才注册,因为我找不到现在正在尝试的确切答案。我希望你能提供帮助。

我正在尝试提取或剪切文件中字符串下的值。我的文件看起来像:

Xmqqstab v1.0 - Developed by Oliver Fisse (ISSW)

 ****
 **** Tuesday, April 26, 2016 10:49:21 AM BST ****
 ****
       UNIX
 Report for queue(s): 'Q1' on queue manager 'QMGR'...

        CQD     PQF      MxQD   OIC   OUC    UNC  LGETDATE  LGETTIME  LPUTDATE  LPUTTIME  QOM G P   Local Queue Name
 ----------------------------------------------------------------------------------------------------------------------------------------------------
          5   0.10%      5000     0     0      0 2016-04-26 10.48.46 2016-04-26 10.49.01  26s E E - Q1

              1 queue(s) matching.

该文件实际上提供了 MQ 队列统计信息,并且我试图获取下面的值,CQD=5(这可以是任何数字)LGETTIME=10.48.46

我可以使用:grep -A3 'CQD' file.txt | sed -n '3p' 来获取值。从这一行开始,我将不得不按列切割值,但我认为这样做并不准确,因为数字可能会像 5 一样变化,在这种情况下可能是四位数字,在这种情况下,列号会改变。

我希望这个问题很清楚。

不胜感激。

谢谢。

【问题讨论】:

  • awk '{print $1}'echo line | tr -s ' ' | cut -d' ' -f1?
  • 无法确定您要查找的输出。只是希望以任何特定语言将值放入数组中,或者您是否正在寻找一种方法来提取“所有符合您标准的行”以便在其他软件或其他软件中进行后处理?跨度>
  • 感谢您的回复。我试图在 CQD 和其他字符串下获取值。科尔的回复有帮助。他的建议是使用: read my_CQD my_LGETDATE

标签: linux shell awk sed grep


【解决方案1】:

你可以这样做:

awk '/CQD/ { for (i = 1; i <= NF; ++i) if ($i == "CQD") col = i } col && $col == 5' file

在与感兴趣的字段名称匹配的行上,遍历每个字段以查找包含它的列。当col 已设置并且列中的值与您想要的匹配时,打印该行(默认操作)。

如果需要,您可以将标题和值作为参数传递给脚本:

awk -v heading=CQD -v value=5 '$0 ~ heading { 
    for (i = 1; i <= NF; ++i) if ($i == heading) col = i 
} col && $col == value' file

使用这两种方法中的任何一种,输出都是以下行:

          5   0.10%      5000     0     0      0 2016-04-26 10.48.46 2016-04-26 10.49.01  26s E E - Q1

...我假设这就是你要找的东西!

【讨论】:

  • 谢谢。但是值 5 不是恒定的,它可以是任何数字。 Cole 的回复有帮助:他的建议是使用: read my_CQD my_LGETDATE
  • ...似乎我误解了您的要求。如果您要做的只是在特定行上打印第 1 列和第 8 列,那么 Cole 的答案看起来就像完成了这项工作。我以为您想搜索特定的行,但不确定要搜索哪些列。
  • @Utku 一个 awk 程序可以有很多对 condition { action }。在这种情况下,col &amp;&amp; $col == 5 是具有默认操作 { print } 的单独条件。
  • @Utku 是的,对于每个输入记录,每对 condition { action } 都适用。
  • @Utku 如果您没有为条件编写{ action } 块,则使用默认的{ print }。在这种情况下,您已经编写了一个动作块。在块内评估为 true 的事物不会触发 print。如果他们这样做,那真的很烦人!
【解决方案2】:

最简单的解决方案是用您选择的分隔符替换您的多个空格,然后cut 就会像您最初计划的那样可靠地工作:

grep -A3 'CQD' file.txt | sed -n '3p' | sed 's/  */_/g'  | cut -f2 -d'_'

这是用下划线代替多个空格的部分:

sed 's/  */_/g' 

【讨论】:

    【解决方案3】:

    sed:

    sed -rn '/CQD.*LGETTIME/{n;n; s/^ *([^ ]* *)([^ ]* *){6}([^ ]*).*/\1\3/p}'
    

    输出:

    $ sed -rn '/CQD.*LGETTIME/{n;n; s/^ *([^ ]* *)([^ ]* *){6}([^ ]*).*/\1\3/p}' file
    5   10.48.46
    

    【讨论】:

      【解决方案4】:

      假设您感兴趣的数据是以数字开头的第一行:

      read my_CQD my_LGETDATE <<< $(awk '$1 ~ /^[0-9]/ {print $1, $8; exit}' file.txt)
      

      说明:

      awk 程序监视第一个字段以数字开头的行。然后它打印由空格分隔的第 1 个和第 8 个字段,然后退出。 Bash 将这两个值读入$my_CQD$my_LGETDATE

      输出:

      echo -e "\$my_CQD: $my_CQD\n\$my_LGETDATE: $my_LGETDATE"
      $my_CQD: 5
      $my_LGETDATE: 10.48.46
      

      【讨论】:

      • 哇,这看起来就像魔术一样。我尝试获取其他值,例如 QOM 等,并且一切正常:)。非常感谢您的帮助。如果你能解释一下它是如何工作的,我已经得到了一些。
      • 我很高兴它有帮助!我已经添加了解释。
      猜你喜欢
      • 1970-01-01
      • 2013-04-10
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 2011-07-21
      • 2019-10-15
      • 1970-01-01
      相关资源
      最近更新 更多