【问题标题】:Using grep and sed to filter through text使用 grep 和 sed 过滤文本
【发布时间】:2014-04-23 03:45:39
【问题描述】:

我有一个文本文件,其中包含一个由 16 位数字和一个名称组成的标题,以及几个被调用的函数:

  00000001000006c0 <_name>:
  ...
  100000730:    e8 8b ff ff ff          callq  1000006c0 <_func1>
  ...
  10000070c:    e8 7f 05 00 00          callq  100000c90 <_func2>
  ...
  0000000100000740 <_otherName>:
  ...
  100000730:    e8 8b ff ff ff          callq  1000006c0 <_func3>
  ...
  10000070c:    e8 7f 05 00 00          callq  100000c90 <_func4>
  ...

我需要从标题中获取名称并将其功能附加到它们。大致如下:

 name -- func1
 name -- func2
 otherName -- func3
 otherName -- func4

我设法通过这个命令得到了标题名称:

 grep -o '\w*>:$' | sed 's/_//' | sed 's/>://' | cat > headingNames.tmp

但我只是以标题名称结束。你能帮我推一下吗?

【问题讨论】:

    标签: shell sed scripting grep


    【解决方案1】:

    我会用 awk+tr 来做

    <INPUT_FILE awk 'NF==2 {header=$2} NF>2 {print header, "--", $NF}' | tr -d '<_>:'
    

    您提供的示例文件的输出:

    name -- func1
    name -- func2
    otherName -- func3
    otherName -- func4
    

    您需要跨行保持状态,因此仅使用 sed 和 grep 会很棘手。另一方面,Awk 非常适合。

    【讨论】:

    • 谢谢,如果没有其他内容,那么这将起作用,然后排在最前面。但我只想打印那些有“callq”标签的。我想这可能会被 grepped,但这会破坏 awk 的功能。
    • 很简单,只需在命令中将 'NF>2' 更改为 'NF>2 && $0 ~ /callq/' 即可。
    【解决方案2】:

    使用 awk:

    awk '{p=$0;gsub(/[<>:]/, "")} p ~ /:$/ && NF==2{name=$2;next} NF>2{print name, "--", $NF} ' file
    _name -- _func1
    _name -- _func2
    _otherName -- _func3
    _otherName -- _func4
    

    【讨论】:

    • 谢谢,如果没有其他东西那么上面的行就行了。但我只想打印那些有“callq”标签的。我想这可能会被 grepped,但这会破坏 awk 的功能。
    • 非常感谢您的帮助。
    【解决方案3】:

    我会使用 Perl,但我确信您可以使用 sed,而且您确实可以:

    /^[0-9a-fA-F][0-9a-fA-F]* </{s/.*<_*\(.*\)>.*/\1/;h;d;}
    /<.*>/{G;s/.*<_*\(.*\)>\n\(.*\)/\2 -- \1/p;}
    d
    

    请不要这样;-)

    除了 callq 之外的抑制输出留给读者作为练习。 (提示:第 2 行。)

    更新:perl 版本,因为 Tom Fenech 想看到它。完全未经修饰,因为做一个 sed 版本更有趣:

    #!/usr/bin/perl -w
    use strict;
    use warnings;
    
    
    my $current = "";
    
    while (<>)
    {
      if (/^[0-9a-f]{16} <_?(.*)>:/)
      {
        $current = $1;
        next;
      }
    
      print "$current -- $1\n" if /.* <(.*)>/;
    }
    

    【讨论】:

    • 我喜欢 Perl 方式 - 我已经尝试了一段时间,但我的正则表达式真的达不到标准!
    • 我认为 SO cmets 有换行符,但这里是:#!/bin/perl -w use strict;使用警告;我的 $current = ""; while () { if (/^[0-9a-f]{16} :/) { $current = $1;下一个; } print "$current -- $1\n" if /.* /; }
    【解决方案4】:

    这可能对你有用(GNU sed):

    sed -nr '/^\s*\S{16}/{h;d};G;s/.*<_(.*)>.*<_(.*)>.*/\2 -- \1/p' file
    

    复制标题,将其附加到非标题行,然后在适用时提取它和函数名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-03
      • 2013-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      相关资源
      最近更新 更多