捕获模式的多个实例
capturing multiple instances of a pattern
我有一个字符串:
{value1}+{value2}-{value3}*{value...n}
使用正则表达式,我想捕获每个括号内的值以及它们之间的运算符,但我不知道会有多少个括号。
我试过了:
/(\{.*\}).*([\+|\-|\*|\/])*/mgU
但这只是让我得到值而不是运算符。我哪里错了?
您可以先使用
验证字符串
/\A ({ [^{}]* }) (?: [\/+*-] (?1))* \z/x
详情:
\A
- 字符串开头
({[^{}]*})
- 第 1 组:{
,除 {
和 }
之外的任何零个或多个字符,然后是 }
字符
(?:[\/+*-](?1))*
- /
、+
、*
或 -
字符出现零次或多次,然后是第 1 组模式
\z
- 字符串结尾。
然后,您可以通过
收集个人比赛
/ { [^{}]* } | [\/+*-] /gx
此正则表达式匹配 {
和 }
(带 {[^{}]*}
)或 /
、+
、[=23= 之间的所有子字符串] 或 -
个字符([\/+*-]
)。
看到一个complete demo script:
#!/usr/bin/perl
use strict;
use warnings;
my $text = "{value1}+{value2}-{value3}*{value...n}";
if ($text =~ /\A ({ [^{}]* }) (?: [\/+*-] (?1))* \z/x) {
while($text =~ / { [^{}]* } | [\/+*-] /gx) {
print "$&\n";
}
}
输出:
{value1}
+
{value2}
-
{value3}
*
{value...n}
另一个想法可能是使用 \G
锚点和 2 个捕获组,其中卷曲值在第 1 组中,运算符在第 2 组中:
\G(?=.*{[^{}]*}\z)({[^{}]*})([+*\/-])?
模式匹配
\G
断言位置在上一个匹配项的末尾,或在字符串的开头(在本例中)
(?=.*{[^{}]*}\z)
正面前瞻,断言字符串以卷曲部分结尾
({[^{}]*})
捕获组 1 中的花括号
([+*\/-])?
可选择捕获第 2 组中的运算符
例子
my $str = "{value1}+{value2}-{value3}*{value...n}";
while ($str =~ /\G(?=.*\{[^{}]*}\z)({[^{}]*})([+*\/-])?/g) {
print "Curly value: Operator: \n";
}
输出
Curly value: {value1} Operator: +
Curly value: {value2} Operator: -
Curly value: {value3} Operator: *
Curly value: {value...n} Operator:
分词器方法:
my @tokens;
for ($str) {
while (1) {
/\G \s+ /xgc;
/\G \{ ( [^{}]* ) \} /xgc
and do { push @tokens, [ VALUE => ]; next; };
/\G ( [+-*\/] ) /xgc
and do { push @tokens, [ OP => ]; next; };
/\G \Z /xgc
and last;
die( "Unexpected character at pos ".( pos )."\n" );
}
}
这可能有点矫枉过正,但更容易扩展。
如果您只有非嵌套块,由已知的运算符列表分隔,则可以使用 split
非常轻松地将语句分成值和运算符。
use strict;
use warnings;
use Data::Dumper;
my @val = split m#([-+/*])#, <DATA>; # parens will prevent operators from being consumed
print Dumper \@val;
__DATA__
{value1}+{value2}-{value3}*{valuen}/{value4}+{value5}-{value6}*{valuen}+{value7}+{value8}-{value9}
这将打印:
$VAR1 = [
'{value1}',
'+',
'{value2}',
'-',
'{value3}',
'*',
'{valuen}',
'/',
'{value4}',
'+',
'{value5}',
'-',
'{value6}',
'*',
'{valuen}',
'+',
'{value7}',
'+',
'{value8}',
'-',
'{value9}
'
];
从那里开始,验证和清理值以及识别运算符应该是一项简单的任务。
我有一个字符串:
{value1}+{value2}-{value3}*{value...n}
使用正则表达式,我想捕获每个括号内的值以及它们之间的运算符,但我不知道会有多少个括号。
我试过了:
/(\{.*\}).*([\+|\-|\*|\/])*/mgU
但这只是让我得到值而不是运算符。我哪里错了?
您可以先使用
验证字符串/\A ({ [^{}]* }) (?: [\/+*-] (?1))* \z/x
详情:
\A
- 字符串开头({[^{}]*})
- 第 1 组:{
,除{
和}
之外的任何零个或多个字符,然后是}
字符(?:[\/+*-](?1))*
-/
、+
、*
或-
字符出现零次或多次,然后是第 1 组模式\z
- 字符串结尾。
然后,您可以通过
收集个人比赛/ { [^{}]* } | [\/+*-] /gx
此正则表达式匹配 {
和 }
(带 {[^{}]*}
)或 /
、+
、[=23= 之间的所有子字符串] 或 -
个字符([\/+*-]
)。
看到一个complete demo script:
#!/usr/bin/perl
use strict;
use warnings;
my $text = "{value1}+{value2}-{value3}*{value...n}";
if ($text =~ /\A ({ [^{}]* }) (?: [\/+*-] (?1))* \z/x) {
while($text =~ / { [^{}]* } | [\/+*-] /gx) {
print "$&\n";
}
}
输出:
{value1}
+
{value2}
-
{value3}
*
{value...n}
另一个想法可能是使用 \G
锚点和 2 个捕获组,其中卷曲值在第 1 组中,运算符在第 2 组中:
\G(?=.*{[^{}]*}\z)({[^{}]*})([+*\/-])?
模式匹配
\G
断言位置在上一个匹配项的末尾,或在字符串的开头(在本例中)(?=.*{[^{}]*}\z)
正面前瞻,断言字符串以卷曲部分结尾({[^{}]*})
捕获组 1 中的花括号([+*\/-])?
可选择捕获第 2 组中的运算符
例子
my $str = "{value1}+{value2}-{value3}*{value...n}";
while ($str =~ /\G(?=.*\{[^{}]*}\z)({[^{}]*})([+*\/-])?/g) {
print "Curly value: Operator: \n";
}
输出
Curly value: {value1} Operator: +
Curly value: {value2} Operator: -
Curly value: {value3} Operator: *
Curly value: {value...n} Operator:
分词器方法:
my @tokens;
for ($str) {
while (1) {
/\G \s+ /xgc;
/\G \{ ( [^{}]* ) \} /xgc
and do { push @tokens, [ VALUE => ]; next; };
/\G ( [+-*\/] ) /xgc
and do { push @tokens, [ OP => ]; next; };
/\G \Z /xgc
and last;
die( "Unexpected character at pos ".( pos )."\n" );
}
}
这可能有点矫枉过正,但更容易扩展。
如果您只有非嵌套块,由已知的运算符列表分隔,则可以使用 split
非常轻松地将语句分成值和运算符。
use strict;
use warnings;
use Data::Dumper;
my @val = split m#([-+/*])#, <DATA>; # parens will prevent operators from being consumed
print Dumper \@val;
__DATA__
{value1}+{value2}-{value3}*{valuen}/{value4}+{value5}-{value6}*{valuen}+{value7}+{value8}-{value9}
这将打印:
$VAR1 = [
'{value1}',
'+',
'{value2}',
'-',
'{value3}',
'*',
'{valuen}',
'/',
'{value4}',
'+',
'{value5}',
'-',
'{value6}',
'*',
'{valuen}',
'+',
'{value7}',
'+',
'{value8}',
'-',
'{value9}
'
];
从那里开始,验证和清理值以及识别运算符应该是一项简单的任务。