为此,我正在尝试描述一个perl脚本:
a = ~b & ~c; ==> a = (~b) & (~c);
a = ~b & (~c); ==> a = (~b) & (~c);所以我使用了先行断言来插入括号,如下所示。这是测试代码。
#!/usr/local/bin/perl5 -w
use strict;
use warnings;
my $line;
my @lines;
@lines = (
"assign a = ~b & ~c;",
"assign a = (~b) & (~c);",
"assign a = ( ~b & ~c );",
"assign a = (b & ~c );"
);
foreach $line (@lines) {
print " $line\n";
$line =~ s/(?!\(\s*)~\w+(?!\s*\))/\($&\)/g;
print ">> $line\n\n";
}它看起来与上面的例子一起工作。然而,它不能与此一起工作。
assign a = ~b & ~c;
>> assign a = (~b) & (~c); <== OK
assign a = (~b) & (~c);
>> assign a = (~b) & (~c); <== OK
assign a = ( ~b & ~c);
>> assign a = ( (~b) & ~c); <== X. I want ( (~b) & (~c));
assign a = ( ~b & ~c );
>> assign a = ( (~b) & ~c ); <== X. I want ( (~b) & (~c) );你能让我知道怎么修改这个脚本吗?谢谢。
发布于 2014-03-08 10:21:52
使用前视和后视断言的目标不会给你带来任何好处。在我看来,将代码分成两个步骤会更容易。一步是捕获前缀为~的变量,第二步是查看它们是否用对括号括起来。
use strict;
use warnings;
while (<DATA>) {
chomp(my $src = <DATA>);
chomp(my $test = <DATA>);
$src =~ s{([(]?~\w+[)]?)}{
my $str = $1;
$str =~ /^\(.*\)$/ ? $str : "($str)";
}eg;
print "test $test\n";
print $src eq $test ? ' ok ' : ' FAIL! ';
print "$src\n";
}
__DATA__
Test:
a = ~b & ~c;
a = (~b) & (~c);
Test:
a = (~b) & (~c);
a = (~b) & (~c);
Test:
a = ( ~b & ~c);
a = ( (~b) & (~c));
Test:
a = ( ~b & ~c );
a = ( (~b) & (~c) );结果:
test a = (~b) & (~c);
ok a = (~b) & (~c);
test a = (~b) & (~c);
ok a = (~b) & (~c);
test a = ( (~b) & (~c));
ok a = ( (~b) & (~c));
test a = ( (~b) & (~c) );
ok a = ( (~b) & (~c) );发布于 2014-03-08 10:23:32
您不能使用单个正则表达式轻松地完成您所要求的操作。
问题是,如果不编写递归正则表达式模式,就无法计算嵌套括号的数量,因此在~c结束时,简单的正则表达式无法知道是否需要使用多少个括号来结束表达式。
使用更复杂的正则表达式可以做到这一点,但是在Perl循环中对字符串进行标记也会容易得多。
你必须处理像a & ~b & c | (d | ~e & f)这样的东西吗?
发布于 2014-03-08 12:09:46
您可以使用一个正则表达式完成此操作,如下所示;
$line =~ s/(?|([^\(])(~\w+)(.)|(.)(~\w+)([^\)]))/$1\($2\)$3/g;
你的reqex不是你想的那样。
$line =~ s/(?!\(\s*)~\w+(?!\s*\))/\($&\)/g;第一部分"(?!(\s*)~“永远不会匹配。记住,lookahead和lookbehinds都是零宽度断言。我喜欢认为它们与字母之间的空格相匹配。(?!(\s*)~意味着,您希望匹配"~“字符,但在”~“字符之前的空格中,您希望向前看,确保不会看到"(”和空格。嗯,如果你在"~“前的空格里,你永远看不到"(”。如果你在"(",前面的负值可能不匹配(如你所愿),但无论如何你都不会匹配"~“。
如果前面的字符不是"(“,后面的字符也不是")”,则会尝试匹配。但是,如果前面的字符不是"(“或后面的字符不是")”,则需要匹配。因此,您需要一个条件分支,如果前面没有"(“,则匹配一个分支,如果后面没有")”,则匹配一个条件分支。
我使用了一个条件分支,(?|告诉引擎像这样存储捕获的子匹配项;
(?|([^\\(])(~\w+)(.)|(.)(~\w+)([^\\)]))
$1 $2 $3 |$1 $2 $3
而不是这个
([^\\(])(~\w+)(.)|(.)(~\w+)([^\\)]))
$1 $2 $3 |$4 $5 $6
我使用(.)要使~\w部分始终为$2,则只需在输出中的$2两边加上"(“”)
我的输出
assign a = ~b & ~c;赋值a= (~b) & (~c);
赋值a= (~b) & (~c);
赋值a= (~b) & (~c);
赋值a=( ~b & ~c );
赋值a=( (~b) & (~c) );
赋值a= (~b & ~c );
赋值a= ((~b) & (~c) );
赋值a=( ~b & ~c );
赋值a=( (~b) & (~c) );
赋值a=( ~b & ~c);
赋值a=( (~b) & (~c));
https://stackoverflow.com/questions/22263972
复制相似问题