+ -
当前位置:首页 → 问答吧 → 请教一个识别后删除的问题

请教一个识别后删除的问题

时间:2010-10-24

来源:互联网

11111

/begin a
22222
/end a

333333

/begin b
44444
/end b

555555

/begin a
66666
77777
/end a

探测到begin后的名字一样的话,就消除/begin到/end行之间的内容.比如上面的文件中删除
/begin a
66666
77777
/end a

一行的删除还有头绪,多行的删除有点没头绪了,
请高手指点!!!谢谢!!

作者: yilong777jp   发布时间: 2010-10-24

本帖最后由 zhlong8 于 2010-10-24 16:48 编辑
  1. use 5.012;
  2. use warnings;

  3. my %tags;       #为 key => [行号1, 行号2, 行号3,...]结构
  4. my @result;
  5. my $line = -1;

  6. while (<>) {
  7.     chomp;
  8.     push @result, $_;
  9.     $line ++;
  10.     if (m!^/begin (\w+)!) {  #记录行号
  11.         exists $tags{$1} ? push(@{$tags{$1}}, $line) : ($tags{$1} = [$line]);
  12.         next;
  13.     }

  14.     if (m!^/end (\w+)!) {    #寻找匹配行号并删除,
  15.                             #不支持 \begin a \begin b \end a \end b这样的交叉结构
  16.         die "not match" unless exists $tags{$1} and @{$tags{$1}};
  17.         splice @result, (pop @{$tags{$1}})-1, $#result; #行号从1 开始,所以要减 1
  18.         $line = $#result;
  19.         next;
  20.     }
  21. }
  22. say for @result;
复制代码
有bug不应该用 $. 已修正

测试数据
  1. 11111

  2. /begin a
  3. 22222
  4. /begin c
  5. 324333
  6. 324234
  7. /end c
  8. /end a

  9. 333333

  10. /begin b
  11. 44444
  12. /end b

  13. 555555
  14. /begin a
  15. 66666
  16. 77777
  17. /end a
复制代码
输出
  1. 11111

  2. 333333

  3. 555555
复制代码

作者: zhlong8   发布时间: 2010-10-24

回复 yilong777jp
  1. perl -lnE '
  2. if (m#/begin (\w+)# .. m#/end ($1)#) {
  3.     say unless $hash{$1};
  4.     m#/end (\w+)# and $hash{$1} = 1;
  5. } else {
  6.     say;
  7. }' txt
复制代码
txt 就是楼主提供的文件,不支持嵌套。

作者: Monox   发布时间: 2010-10-24