【问题标题】:qr operation in perl 5.16perl 5.16 中的 qr 操作
【发布时间】:2017-08-01 18:50:33
【问题描述】:

我正在尝试修复一个非常旧的脚本,该脚本试图在文本文件中查找字符串 FILE_DESC_LIMIT 并将其更改为其他内容。

为此,我当前的脚本在 Perl 5.10 上运行良好,我看到它使用正则表达式

    qr!^FILE_DESC_LIMIT=\d+(\s*)!;

但这在 Perl 5.16 中不起作用,所以我尝试打印这个表达式。 在 5.10 中我看到了

    (?-xism:\bFILE_DESC_LIMIT=\d+(\s*))

在 Perl 5.16 中我看到了

    (?^:^FILE_DESC_LIMIT=\d+(\s*))

我看到 qr 是在添加 -xism 而在 5.16 中没有添加,为什么这里有区别?

如果我在正则表达式中显式添加它,它会起作用。但我怀疑这个解决方案,因为 Perl 没有明确添加它,这里可能存在一些问题。

我应该为 Perl 5.16 使用一些不同的方法吗? 为什么 Perl 改变了这种行为?

我的代码看起来像这样,我们正在创建一个正则表达式,然后使用正则表达式我们制定一个表达式,然后在打开的文件上进行评估,然后将评估的输出写入同一个文件。

my atempRegex=qr!^FILE_DESC_LIMIT=\d+(\s*)!;
my $replaceSting => qq!FILE_DESC_LIMIT=$FileDescLimit\$1!

$tempRegex =~ s!\^!\\b!g if ($] =~ /5\.010/);

my $code .= "\$File =~ s!$tempRegex!$replaceSting!gsm;\n";

open (FH, "<$WORKING_DIR/$base_script_name.$$.tmp") || logWrite2(E,"-- 
ERROR: Unable to open $WORKING_DIR/$base_script_name.$$.tmp for reading 
($!)");

my $File = join("",<FH>);
close (FH);

eval $code;

open (FH, ">$WORKING_DIR/$base_script_name.$$.tmp") || logWrite2(E,"-- 
ERROR: Unable to open $WORKING_DIR/$base_script_name.$$.tmp for writing 
($!)");

print FH $File;
close (FH);

我为使其在 perl 5.16 中工作所做的更改是,我将 -xism 修饰符显式添加到正则表达式中,并修改了 \b 修饰符条件

my $FileDescLimit=2048;
my $tempRegex=qr!^FILE_DESC_LIMIT=\d+(\s*)!;
my $replaceSting => qq!FILE_DESC_LIMIT=$FileDescLimit\$1!

if ($] >=5.016)
{
    $tempRegex=~ s!\^!-xism!;
}
$tempRegex =~ s!\^!\\b!g if ($] >=5.010);

my $code .= "\$File =~ s!$tempRegex!$replaceSting!gsm;\n";

open (FH, "<$WORKING_DIR/$base_script_name.$$.tmp") || logWrite2(E,"-- ERROR: Unable to open $WORKING_DIR/$base_script_name.$$.tmp for reading ($!)");

my $File = join("",<FH>);
close (FH);

eval $code;

open (FH, ">$WORKING_DIR/$base_script_name.$$.tmp") || logWrite2(E,"-- ERROR: Unable to open $WORKING_DIR/$base_script_name.$$.tmp for writing ($!)")
print FH $File;
close (FH);

我不知道问题是因为 -xism 修饰符还是因为 \b 修饰符,因为我看到脚本是在 5.10 版上修改的,并且明确添加了 \b 修饰符,可能真正的问题出在这个修饰符上。

参考下面的答案之一, ?^ 相当于 ?-xism ,我删除了代码

if ($] >=5.016)
{
    $tempRegex=~ s!\^!-xism!;
}

从我的脚本中,所以 -xism 不再是我的正则表达式的一部分,并且我在我的正则表达式中添加了 \b,就像为 perl 版本 5.10 所做的那样,下面的代码替换了我的正则表达式中的第二个插入符号,(?^:^ FILE_DESC_LIMIT=\d+(\s*)) 与 \b,结果正则表达式 (?^:\bFILE_DESC_LIMIT=\d+(\s*)) 匹配并替换字符串

if ($] =~ /5\.016/)
{
    my $n=0;
    $Source =~ s/\^/++$n==2?"\\b":"\^"/ge
}

正如我在正则表达式教程中看到的 \b 用于定义单词边界并执行整个单词匹配,我不清楚为什么它无法匹配 FILE_DESC_LIMIT=2048 文件中没有\b的字符串。

【问题讨论】:

  • “这不起作用”是什么意思?
  • 需要更多细节 - 更多的脚本将是一个很好的起点。简短的回答是 - 它可能 没有 改变你的正则表达式,只是它的显示方式。 (?^: 是'没有修饰符',?-xism 也意味着'没有x,没有i,没有s,没有m
  • 看起来它已在 5.16 中修复,因为它保留了 ^ 而不是将其更改为 \b
  • @ChrisTurner: “它保留了 ^ 而不是将其更改为 \b 我认为 Perl v5.10 不太可能进行这种更改。 OP 更可能犯了转录错误。
  • @Borodin 是的,但我们只能处理问题中的内容

标签: perl perl5.16


【解决方案1】:

documentation on Extended Patterns in perlre 有这个

从 Perl 5.14 开始,紧跟在 "?" 之后的 "^"(插入符号或抑扬符)是等同于 d-imnsx 的简写。标志("d" 除外)可以跟随插入符号来覆盖它。但是减号是不合法的。

在这些修饰符中,-imsx 与您在 v5.10 中看到的匹配,而 -n 启用括号的捕获行为,d 启用“默认”字符集行为。最后两个是新的修饰符

这些都与您在 v5.10 中显示的值没有任何不同,因此您必须显示您的数据以及您所写的内容才能改变行为

【讨论】:

    【解决方案2】:

    参见Regular Expressions in Perl 5.14 Delta(?^ 现在表示默认修饰符。只是编译后的正则表达式如何序列化的问题,更重要的是你的正则表达式中\b^的区别。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-06
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 2011-09-14
      • 2016-04-10
      相关资源
      最近更新 更多