尝试匹配Perl程序中某个文件的某些数据模式。由于匹配可能超过多行,因此我将行分隔符设置为未定义。
$/ = undef ;
现在,因为匹配可以跨越多行而不止一行,所以我使用了smgi修饰符。
if ( $msgText =~ /$msgTypeExpr/smgi )
现在,我遇到的问题是上面的变量$ msgText被修改了,虽然我没有替换它。
以下是相关代码:
open (HANDLE1,"$file") || die "cannot open file \n";
$/ = undef ;
while ( my $msgText = <HANDLE1> )
{
my $msgTypeExpr = "<city\\W+";
print "Attempt 1:\n";
if ( $msgText =~ /$msgTypeExpr/smgi )
{
print "matched\n";
}
else
{
print " not matched \n";
}
print "Attempt 2:\n";
if ( $msgText =~ /$msgTypeExpr/smgi )
{
print "matched\n";
}
else
{
print " not matched \n";
}
}
测试输入文件如下所示:
<city
name="abc">
</city>
人们会期望模式匹配两次但它只匹配第一次而不是第二次匹配。
我暂时解决了这个问题,在匹配和使用该temp变量匹配之前,暂时分配一个临时变量。
my $tmpMsgText = $msgText ;
这是我第一次在这个论坛上发帖提问,所以请原谅我所犯的任何礼仪错误,也请你好好指出,以便我将来不再重复。
答案 0 :(得分:2)
首先,我不确定是否会阅读这样的文件。修改那些Perl特殊变量,比如$ /应该用local来完成,如下所示:
local $/ = undef;
这样,变量仅在当前范围内进行修改(从而消除了可能的远距离错误)。通过将$ /设置为undef,您将一次性读取整个文件,因此没有必要在其中放置while循环。我会像这样阅读整个文件:
open my $fh, "<", "somefile" or die;
my $content = do { local $/ = undef; <$fh> };
do块仅将修改后的$ / value限制为该一个语句(它创建一个新范围)。
关于正则表达式匹配:在正则表达式后删除/ g修饰符。如果我没记错的话,它会记住最后一个正则表达式搜索位置并从那里继续。同样,为了检测字符串是否被更改,请在这些匹配之前和之后打印变量。你会看到,他们没有被修改。 而不是:
if ( $msgText =~ /$msgTypeExpr/smgi )
放:
if ( $msgText =~ /$msgTypeExpr/smi )
答案 1 :(得分:2)
if (//g)
毫无意义。 “如果它匹配并继续匹配,直到没有匹配”?摆脱g
。
我不知道你为什么使用s
或m
。
s
没用,因为该模式不包含.
。
m
没用,因为该模式不包含^
或$
。
实际上,标量上下文中的//g
充当迭代器。
$ perl -E'$_ = "abc"; /(.)/g && say $1; /(.)/g && say $1;'
a
b