【问题标题】:Perl pattern match variable questionPerl 模式匹配变量问题
【发布时间】:2011-06-04 07:08:58
【问题描述】:

我正在尝试打开一个文件,匹配特定的行,然后在该行周围环绕 HTML 标记。看起来非常简单,但显然我遗漏了一些东西并且没有正确理解 Perl 匹配的模式变量。

我将这条线与此匹配:

$line =~ m/(Number of items:.*)/i;

这会将整行放入 $1。然后我尝试像这样打印出我的新行:

print "<p>" . $1 . "<\/p>;

我希望它打印这个:

<p>Number of items: 22</p>

但是,我实际上得到了这个:

</p>umber of items: 22

我尝试了各种变体 - 将每个位打印在单独的行上,将 $1 设置为新变量,使用 $+ 和 $& 等等,我总是得到相同的结果。

我错过了什么?

【问题讨论】:

  • 你所描述的在我的机器上工作。您可以发布您正在运行的实际代码吗?
  • 请包含您使用的完整(但最少)代码。

标签: regex perl backreference


【解决方案1】:

您刚刚了解到(供将来参考).* 的危险程度。

在经历过类似的不愉快之后,这些天我喜欢尽可能准确地描述我希望捕捉的内容。也许

$line =~ m/(Number of items:\s+\d+)/;

那么我肯定不会首先捕获有问题的控制字符。无论 Cygwin 对 Windows 文件做什么,我都可以保持无知。

【讨论】:

    【解决方案2】:

    您的比赛中有一个 \r,当打印时会导致格式错误的输出。

    编辑: 为了进一步解释,您的文件可能具有 Windows 样式 \r\n 行尾。 chomp 不会删除 \r,然后它会进入你的贪婪匹配,并导致令人不快的输出(\r 表示回到行首并继续打印)。

    您可以通过添加类似

    的内容来删除 \r
    $line =~ tr/\015//d;
    

    【讨论】:

    • 鉴于所述行为,这是一个很好的猜测。迂腐/澄清:默认情况下chomp 不会删除\r,但如果您更改$/ 则可以。通常这不是必需的,因为 perlio 层将在输入/输出期间在平台换行符和逻辑换行符之间进行转换。需要注意的是,如果文件格式与平台不匹配(例如,在 *nix 平台上处理带有 Windows 样式换行符的文件),则翻译不起作用。
    • 这似乎是问题所在 - 我正在使用 Cygwin 并读取 Windows 文本文件。我正在 chomp()ing 行,但显然没有得到 \r。这对我以前做过的任何事情都不是问题,而且文本被替换的方式并没有让我想到这一点。我现在明确替换 \r 并且它工作正常。谢谢!
    【解决方案3】:

    您能否提供一个完整的代码 sn-p 来演示您的问题?我没看到。

    需要注意的一点是,$1 和朋友指的是在该动态范围内上一次成功匹配 中的捕获。在使用匹配之前,您应该始终验证匹配是否成功:

    $line = "Foo Number of items: 97\n";
    if ( $line =~ m/(Number of items:.*)/i ) {
        print "<p>" . $1 . "<\/p>\n";
    }
    

    【讨论】:

    • 真的很好。我被上一场比赛挂在上面的 $1 等咬伤了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    相关资源
    最近更新 更多