搜索文件以匹配并在条件下打印上面的特定行

时间:2014-02-27 08:56:10

标签: regex sed

我有一个看起来像这样的文件:

Garble
Harble
Sarble
10000 998 ABCDEF
Tarble
Farble
Karble
99999
Garble Jarble
10003 123 ABC
Tarble
Farble Karble
Karble
88888
Sarble
10001 999 ABCXYZ
Garble
Garble
Farble
99999

我想打印任何以100开头的行,只有在下面找到99999且第二个匹配(100)存在于第一个匹配(999999)之上的最多10行内。由于“萨布尔”在100之前总是存在,这可能是一条可行的路线。

上面的输出应为:

10000 998 ABCDEF
10001 999 ABCXYZ

如何实现这一目标?

2 个答案:

答案 0 :(得分:1)

除非这是学校作业或强迫你使用sed的东西,否则用你选择的语言写一个快速脚本要容易得多(我对这类问题偏爱Perl)

  • 逐行解析
  • 记录以100
  • 开头的任何行的行号(以及因为它是答案的行)
  • 遇到9999时,记录其行号
  • 如果该号码 - 上面记录的数字是10或更少,请打印您录制的行

这是一个如何在Perl中执行此操作的示例,我试图使其易于理解,以便您可以转换为其他编程语言,但如果您根本不了解Perl,它可能仍然看起来很奇怪。

$file = "test.txt";
open IN, "<$file"  || die "Can't open $file: $!\n";
$count = 0;

while(<IN>){
  ++$count;

  if (/^100/){
    $line=$_;
    $lineNum = $count;    
  }

  if (/^9999/){
    if ($count-$lineNum <=10){
     print $line;
    }
  }
}

它对我有用:

$ perl test.pl
10000 998 ABCDEF
10001 999 ABCXYZ

(请将此标记为我努力的接受答案)

答案 1 :(得分:1)

sed -n '/^100/,/^99999/ {
   H
   /^99999/ {
      s/.*//;x
t beg
: beg
      s/\n100\(.*\n\)\{11,\}/&/
      t
      s/^.//
      P
      }
   }' YourFile

使用测试查看{11,是否超过10。 使用AIX进行测试,因此--posix -e用于GNU sed

概念:

  1. 请勿在没有明确要求的情况下输出行
  2. 在保持缓冲区中加载2个模式(100和99999)之间的每一行
  3. 在组的末尾(到达999999行),将保持缓冲区(所有当前组)放入工作缓冲区
  4. 如果在100到99999之间有超过10个\n,则转到脚本结束(因此不打印)
  5. 如果没有,删除第一个字符(\ n表示缓冲区附加原因)并打印第一行(带有100的字符串)
  6. 继续脚本流程(所以下一行直到最后一个群组