如何将可变多行Perl正则表达式与不同规则匹配

解析器api(不允许修改)给了我这种形式的字符串:

    var1    var2  \
var2continued var2continued   \\\
var2continued
var3
var3continued \

var3continued

我想使用正则表达式分割此字符串,例如:

$1 = "var1";
$2 = "var2  
var2continued var2continued   \\
var2continued"
$3 = "var3
var3continued \

var3continued"

基本上,第一个变量是一个或多个空格后的第一个非空格字,遇到空间时结束。

第二个变量从第一个变量之后的第一个非空格字符开始,直到行尾。如果最后一个字符是“ \”,则将下一行添加到第二个变量中(不要修剪当前行最后一个字符和“ \”之间的空白)。 “ \”不应捕获下一行,而应同时返回两个“ \”(无转义)。仅修剪最后一行的空白。

第三变量是第二变量之后的所有内容。

到目前为止,我已经能够提出这个正则表达式,它仅适用于var2和var3的一行

$my_re = qr/\s+(\S+)\s+(\S+)\s+[\n](.*)/

$text =~ /$my_re/

daodan_9 回答:如何将可变多行Perl正则表达式与不同规则匹配

第一个单词,然后是直到换行符的所有内容,其后立即加上一个非斜杠;然后所有其他

/\s+ (\S+) \s+ (.*?[^\\]) \n (.*)/xs;

通过/s修饰符可以使.也与换行符匹配,这在此处很重要(通常不匹配)。 /x修饰符使其忽略文字空间,因此我们可以使其更具可读性。


示例程序

use warnings;
use strict;
use feature 'say';

my $v = 
q(    var1    var2  \
var2continued var2continued   \\\
var2continued
var3
var3continued \

var3continued);

$v =~ /\s+ (\S+) \s+ (.*?[^\\]) \n (.*)/xs;

say "\"$1\"";  say '---';
say "\"$2\"";  say '---';
say "\"$3\""; 

打印

"var1"
---
"var2  \
var2continued var2continued   \\
var2continued"
---
"var3
var3continued \

var3continued"
,

尝试下面的代码(我来解决这个问题)

use strict;
use warnings;

my $str = do { local $/; <DATA> };

print "INPUT:\n[$str]\n";

$str =~ /(\w+)\s+(.*?\\\\\\\s*\w+)\n(.+)/s;
#$str =~ /(\w+)\s+((?:.*?)\\\\\\\s+(?:\w+)?)\n(.+)/s;

print "\n1: [$1]";
print "\n2: [$2]";
print "\n3: [$3]";

__DATA__
    var1    var2  \
var2continued var2continued   \\\
var2continued
var3
var3continued \

var3continued

输出

INPUT:
[    var1    var2  \
var2continued var2continued   \\\
var2continued
var3
var3continued \

var3continued
]

1: [var1]
2: [var2  \
var2continued var2continued   \\\
var2continued]
3: [var3
var3continued \

var3continued
]
,

所有情况下都没有答案(2和3是可选的)。我有一个小问题,解析器在反斜杠后添加空间。

我最终将文本分成多行。然后将其分为两部分(1和2在一起,以及3本身)。然后我将其分为第一部分。我的实际代码分为多个功能,但在下面进行了简化:

my $empty_re = qr/^\s*$/;
my $def_re = qr/(.*?)((?:\\{2})*)(\\?)\s*$/;
my $dual_token_re = qr/\s*(\S+)\s*(.*)/s;
$text= "place text here"
my @lines = split /\n/,$text;
my $i;
my $j;
my $def = "";
my $other;
# Get start capture
for($i=0;$i<=$#lines;$i++){
    last if !($lines[$i] =~ /$empty_re/);
}

# Start definition capture
for($j=$i;$j<=$#lines;$j++) {
    $lines[$j] =~ s/$def_re/$1$2/; # remove ending backquote if odd
    last if !$3; # break if even backquotes
}
$def = join "\n",@lines[$i..$j];
$j++;

# Get remaining text
if ($j <= $#lines) {
    $other = join "\n",(splice @lines,$j);
}

# $def has 1 and 2,$other has 3

$def =~ /$dual_token/
# now $1 and $2 has 1 and 2,$other has 3

本文链接:https://www.f2er.com/2811207.html

大家都在问