1

我试图从 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>

人们会期望该模式匹配两次,但它只匹配第一次而不是第二次。

我已经暂时解决了这个问题,在匹配之前先分配给一个临时变量,然后使用该临时变量进行匹配。

my $tmpMsgText = $msgText ;

这是我第一次在这个论坛上发布问题,所以请原谅我可能犯的任何礼仪错误,也请您指出它们,以便我以后不再重复。

4

2 回答 2

2

if (//g)没有意义。“如果它匹配并继续匹配直到没有匹配”?摆脱g.

我不知道你为什么使用sm两者之一。

是没用的s,因为模式不包含..

是没用的m,因为模式不包含^or $


实际上,//g在标量上下文中充当迭代器。

$ perl -E'$_ = "abc"; /(.)/g && say $1; /(.)/g && say $1;'
a
b
于 2013-11-14T14:04:00.300 回答
2

首先,我不确定是否要读取这样的文件。修改那些 Perl 特殊变量,比如 $/ 应该用本地来完成,像这样:

local $/ = undef;

这样,变量仅在当前范围内被修改(从而消除了可能的远距离操作错误)。通过将 $/ 设置为 undef,您将一次性读取整个文件,因此在此处放置 while 循环是没有意义的。我会像这样阅读整个文件:

open my $fh, "<", "somefile" or die;
my $content = do { local $/ = undef; <$fh> };

do 块将修改后的 $/ 值仅限于该一个语句(它创建一个新范围)。

关于正则表达式匹配:删除正则表达式后的 /g 修饰符。如果我没记错的话,它会记住最后一个正则表达式搜索位置并从那里继续。同样为了检测字符串是否被更改,在这些匹配之前和之后打印变量。你会看到,它们没有被修改。代替:

if ( $msgText =~ /$msgTypeExpr/smgi )

放:

if ( $msgText =~ /$msgTypeExpr/smi )
于 2013-11-14T13:02:32.293 回答