匹配Perl中的多个行字符串

时间:2015-04-11 18:46:05

标签: regex perl

我是Perl的新手,我想知道是否有人可以帮助我。

我有这样的输入:

a,b,
c,d,e,f,g,h,
i,j,q // Letras

我试图分别在//之前获取字母,然后在{}之间以:分隔。{/ p>

我尝试了这个RE ([\w,;:\s\t]*)(\n|\/\/)/m,我可以在$1中获取每一行的所有字母(作为包含分隔符的字符串),但不是我想要的。

我需要在同一个文件中多次匹配该模式,因此我使用的是/g

编辑:

这是我的代码块:

while ( <> ) {
  if ( /([\w,;:\s\t]*)(\n|\/\/)/m ) {
    print "$1\n";
  }
} 

4 个答案:

答案 0 :(得分:2)

/m用于使用^$来匹配多行中字符串中的行。

另一方面,您正在逐行阅读输入 。如果您一次只查看一行,则不能指望使用单个表达式跨行匹配。

相反,通过将$/设置为适当的值来读取块。如果块总是以精确的字符串"// Letras\n\n"结束,则任务更简单。

#!/usr/bin/env perl

use strict;
use warnings;

local $/ = '//';

while (my $chunk = <DATA>) {
    chomp $chunk;
    my @fields = ($chunk =~ /([a-z])[, ]/g);
    next unless @fields;
    printf "{%s}\n", join(':', @fields);
}

__DATA__
a,b,
c,d,e,f,g,h,
i,j,q // Letras

a,b,
c,d,e,f,g,h,
i,j,q // Metras

输出:

{a:b:c:d:e:f:g:h:i:j:q}
{a:b:c:d:e:f:g:h:i:j:q}

您还可以使用File::Stream

#!/usr/bin/env perl

use strict;
use warnings;

use File::Stream;

my $stream = File::Stream->new(
    \*DATA,
    separator => qr{ (?: \s+ // [^\n]+ ) \n\n }x
);

while (my $chunk = <$stream>) {
    $chunk =~ s{ \s+ // .* \z }{}sx;
    $chunk =~ s{ ,\n? }{:}gx;
    print "{$chunk}\n";
}

__DATA__
a,b,
c,d,e,f,g,h,
i,j,q // Letras

a,b,
c,d,e,f,g,h,
i,j,q // Metras

答案 1 :(得分:1)

认为你的目标是从每一行中删除注释(用双斜杠表示),然后用大括号括起来,并用冒号{{1分隔符而不是逗号

首先,您应该使用:

从每行中删除尾随换行符

然后您需要删除任何结尾的评论chomp。这也会删除s|\s*//.*||之前的所有空格。我使用管道符//作为分隔符,以避免必须在正则表达式模式中转义斜杠。并且数据一次处理一行,因此不需要全局 |修饰符

此程序从命令行中指定的文件中读取,我已将其设置为包含您在问题中显示的数据

/g

<强>输出

use strict;
use warnings;

while ( <DATA> ) {
  chomp;
  s|\s*//.*||;
  print "{$_}\n";
}

<强>更新

感谢Sinan Ünür's solution我注意到您已经要求&#34;在[{1}}之间打印[{1}} {a,b,} {c,d,e,f,g,h,} {i,j,q} &#34; < / em>的

这是对上面{}循环的修改,它会查找当前行中不包含逗号的所有子字符串,并使用冒号:再次将它们连接在一起

while

<强>输出

:

我确信真正的解决方案要简单得多,但除非你详细说明你的问题,否则我们必须迎合所有可能性

答案 2 :(得分:0)

您是否希望将所有3行的字母组合到输出中,或转换每行?

换句话说,是您想要的输出

{a:b}
{c:d:e:f:g:h}
{i:j:q}

{a:b:c:d:e:f:g:h:i:j:q}

如果你想要前者,鲍罗丁的回答是可行的。 如果你想要后者,那么你应该将内容加载到一个数组中,并使用join语句打印它。为此,我修改了鲍罗丁的答案:

while ( <> ) {    # read each line
  chomp;          # remove \n from line
  s|\s*//.*||;    # remove comment
  push @values, ':', /[^,]+/g;   # store letters in array
}
my $values = join ':', @values;  # convert array to string
print "{$values}\n";             # print the results

答案 3 :(得分:0)

my $str = "a,b,
c,d,e,f,g,h,
i,j,q // Letras";

$str = join "",map {s/,/:/g ;(split)[0]}  split '\n', $str;

print "{$str}";


Sample output

{a:b:c:d:e:f:g:h:i:j:q}

我正在考虑一个由换行符分隔的多行的字符串。

join "",map {s/,/:/g ;(split)[0]}  split '\n', $str 

这是从右到左评估的。

  1. \n上与$str分开,会产生3个元素,这些元素是map的输入。

  2. (split)[0]split的默认分隔符是空格。所以每个元素都被拆分为空格,而0th元素只被视为丢弃其他元素。 (split)[0]的Ex i,j,q // Letras产生3个元素“i,j,q”“//”“Letras”,其中只考虑元素0即“i,j,q”。

    < / LI>
  3. ,已替换为:

  4. join用于合并map中的所有结果元素。