perl - 将子字符串提取到计数为零或更多的字符

时间:2016-11-29 14:07:05

标签: regex string perl

我在文件中有以下字符串

1. aaa bbb zccc ddd eee; 
2. yyaaa bbb zccc dzdd eee;  ('z' is present multiple times)
3. yyaaa bbb ccc *zddd eee;  (special character '*' present)
4. yyaaa bbb ccc * zddd eee; (special character '*' present)
5. aaa bbb ccc* zddd eee;    (special character '*' present)
6. aaa bbb ccc ddd eee;      ('z' is absent)

另一个示例文件

1. aaa bbb zccc ddd eee; 
2. yyaaa bbb zccc dzdd eee;
3. yyaaa bbb *ccc * zddd eee;
4. yyaaa bbb * ccc zddd eee;
5. aaa bbb* ccc zddd eee;
6. aaa bbb ccc ddd eee;

在每一行中,我想从aaa的末尾提取子串到z的第一个存在(减去z)。如果z不存在,则应打印整个字符串。如果有特殊字符,则应省略它们。

需要的输出

bbb
bbb
bbb ccc
bbb ccc
bbb ccc
aaa bbb ccc ddd eee

我已尝试过以下内容,但它没有提供我正在寻找的输出

my $file = qq(test.txt);
open (my $IN, '<', $file) || die "Cannot open $file for read: $!";     
my @lines=<$IN>;  
close($IN);

foreach (@lines)
{
    if( $_ =~ m/aaa\b(.*?)z/)
    {
        print "$1\n";
    } 
}

我的输出

bbb
bbb
bbb ccc *
bbb ccc *
bbb ccc*

我不确定如何排除特殊字符(尝试过的字符类),并且它不会为没有'z'字符的第6行输出任何内容。

2 个答案:

答案 0 :(得分:3)

我认为这就是你想要的

请注意,单个捕获中无法排除“特殊”字符,因此必须分两个阶段完成

你的“必需输出”比相应的输入行有更少的空格,但是你没有在文本中提到任何内容,所以无法知道你真正想要的是什么

use strict;
use warnings 'all';

while ( <DATA> ) {

    next unless /a+\s+((?:(?!\s*z).)+)/;

    (my $val = $1) =~ tr/*;//d;

    print $val, "\n";
}



__DATA__
1. aaa bbb zccc ddd eee; 
2. yyaaa bbb zccc dzdd eee;
3. yyaaa bbb *ccc * zddd eee;
4. yyaaa bbb * ccc zddd eee;
5. aaa bbb* ccc zddd eee;
6. aaa bbb ccc ddd eee;

输出

bbb
bbb
bbb ccc 
bbb  ccc
bbb ccc
bbb ccc ddd eee

答案 1 :(得分:0)

您可以使用否定字符类

if( $_ =~ m/aaa\b([^z;]*)/)
{
    $string = $1;
    $string =~ s/\*//g;
    print "$string\n";
}
# Outputs
# bbb
# bbb
# bbb ccc
# bbb ccc
# bbb ccc
# bbb ccc ddd eee
  • [^z;]*匹配z;
  • 以外的任何内容
  • $string =~ s/\*//g;替换组中的*