代码之家  ›  专栏  ›  技术社区  ›  William Pursell

为什么m/$/m会给我带来意想不到的行为?

  •  0
  • William Pursell  · 技术社区  · 15 年前

    What regular expressions can never match? /$./ 作为回应。我稍微玩弄了一下,发现下面两行代码生成了不同的输出。第二个匹配,但第一个不匹配。有人能解释为什么吗?

    $ printf 'a\nb\n' | perl -0777 -ne 'print if m/$./m'
    $ perl -0777 -e '$_="a\nb\n"; print if m/$./m'
    

    另外,请注意,在以下内容中添加<gt;会导致匹配失败:

    $ printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; say $b =~ m/$./m'
    $ printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; <>; say $b =~ m/$./m'
    

    (即,第一个打印“1”,第二个打印空行)

    4 回复  |  直到 15 年前
        1
  •  9
  •   Brad Gilbert    15 年前

    打开警告会提示原因:

    $ printf 'a\nb\n' | perl -0777 -w -e 'use feature qw/say/; $b = "a\nb\n"; say $b =~ m/$./m'
    Use of uninitialized value $. in regexp compilation at -e line 1.
    1
    

    您在regex中使用了未定义的值。序列 $. refers to the special variable for the line number of the last-accessed file handle . 它确实 将正则表达式指定为“行尾后跟任何字符”。由于您没有访问任何文件,因此它仍然是未定义的,因此regex是空的。当你使用 -n 选项,它有效地将程序的其余部分 while (<>) { ... } 所以你读 <> 最后结束 1 在里面 美元。 因为你读过一行。

    当你说 <> 在第二次尝试中,您访问了stdin文件句柄。现在正则表达式是 m/1/m ,与输入字符串不匹配。

        2
  •  6
  •   Michael Carman    15 年前

    这个 $. 在您的regex中,被解析为特殊变量的值 美元。 ( $INPUT_LINE_NUMBER )而不是“行尾后跟任何字符”。

    还要注意, /m 修饰符改变了 $ 从字符串末尾的匹配到字符串中任何位置结束的匹配。见 Modifiers 在伯勒。这意味着在它之后可以有一些内容(使用适当的修改器):

    say "a\nb\n" =~ m/$ ./msx;
    

    打印“1”。这个 /x 修饰符允许使用嵌入的空白,因此我们可以将 $ . 以避免它被解释为变量。

        3
  •  5
  •   Ivan Nevostruev    15 年前

    这段代码为我打印了“坏管道”,因为Perl不希望在这里输入任何内容。它还使用未定义的变量 $. (如果你想增加 -w 切换到perl)。这个变量 美元。 表示当前行号,然后按 <...> . 这就是为什么在这个例子中它是未定义的:

    ## matching pattern will look like m//m
    printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; say $b =~ m/$./m'
    

    以下代码读取管道数据,但将不匹配,因为 美元。 之后等于1 <> . 匹配模式变成 m/1/m 以下内容:

    ## matching patter will be m/1/m, which is not found in $b value
    printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; <>; say $b =~ m/$./m'
    

    更新:

    使用 m'$.'m m/$ ./mx (感谢迈克尔·卡曼)禁用变量插值。

        4
  •  0
  •   Dan    15 年前

    首先,我认为这是因为-n开关。换言之

    printf 'a\nb\n' | perl -0777 -ne 'print if m/$./m'
    

    使$获得值 a\n 第一次通过循环 b\n 第二次显然是不匹配的。而with/m$与第二个示例中的\n匹配,所以这就是匹配的原因。

    接下来的两个例子,我仍在研究它:)

    编辑:哇,我完全错了,我想你也错了。问题是 m/$./m 一行的结尾,后面跟一个通配符,而不是变量$。插入为正则表达式。伊克斯!