12

文字列"aa\ nbb \ ncc"の場合、左の最後の文字から最初の改行( "a")まで、複数行の文字列の最後まで一致させたいので、

"aa\nbb\ncc" =~ qr/( . $ .+ )/xms一致するa\nbb\ncc

そしてそれ

"aa\nbb\ncc\n" =~ qr/( . $ .+ )/xms一致し a\nbb\ncc\nます。

しかし、私は一致するものがなく、一致するものもあり"aa\nbb\ncc" =~ qr/( . $ .+ )/xms ません。c\n"aa\nbb\ncc" =~ qr/( . $ .+ )/xms

を使用するqr/( . $ ..+ )/xmsと、期待どおりの結果が得られました(サンプルコードを参照)。

Perlバージョン5.14.2。

誰かがその行動について説明できますか?

perldoc perlre:

   m   Treat string as multiple lines.  That is, change "^" and "$" 
       from matching the start or end of the string to matching the start 
       or end of any line anywhere within the string.

   s   Treat string as single line. That is, change "." to match any character 
       whatsoever, even a newline, which normally it would not match.

       Used together, as "/ms", they let the "." match any character whatsoever, 
       while still allowing "^" and "$" to match, respectively, just after and 
       just before ewlines within the string.

   \z  Match only at end of string

次のサンプルコードを実行します。

#!/usr/bin/env perl

use strict;
use warnings;

print "Multiline string : ", '"aa\nbb\ncc"', "\n\n";
my $str = "aa\nbb\ncc";

print_match($str, qr/( . $ )/xms);       # matches "a"
print_match($str, qr/( . $ . )/xms);     # matches "a\n"
print_match($str, qr/( . $ .. )/xms);    # matches "a\nb"
print_match($str, qr/( . $ ..+ )/xms);   # matches "a\nbb\ncc"
print_match($str, qr/( . $ .+ )/xms);    # NO MATCH ! Why ???
print_match($str, qr/( . $ .+ \z )/xms); # NO MATCH ! Why ???

print "\nMultiline string now with terminating newline : ", '"aa\nbb\ncc\n"', "\n\n";
$str = "aa\nbb\ncc\n";

print_match($str, qr/( . $ )/xms);       # matches "a"
print_match($str, qr/( . $ . )/xms);     # matches "a\n"
print_match($str, qr/( . $ .. )/xms);    # matches "a\nb"
print_match($str, qr/( . $ ..+ )/xms);   # matches "a\nbb\ncc\n"
print_match($str, qr/( . $ .+ )/xms);    # MATCHES "c\n" ! Why ???
print_match($str, qr/( . $ .+ \z)/xms);  # MATCHES "c\n" ! Why ???

sub print_match {
    my ($str, $regex) = @_;
    $str =~ $regex;
    if ( $1 ) {
        printf "--> %-20s matched : >%s< \n", $regex, $1;
    }
    else {
        printf "--> %-20s : no match !\n", $regex;
    }
}

出力は次のとおりです。

Multiline string : "aa\nbb\ncc"

--> (?^msx:( . $ ))      matched : >a<
--> (?^msx:( . $ . ))    matched : >a
<
--> (?^msx:( . $ .. ))   matched : >a
b<
--> (?^msx:( . $ ..+ ))  matched : >a
bb
cc<
--> (?^msx:( . $ .+ ))   : no match !

Multiline string now with terminating newline : "aa\nbb\ncc\n"

--> (?^msx:( . $ ))      matched : >a<
--> (?^msx:( . $ . ))    matched : >a
<
--> (?^msx:( . $ .. ))   matched : >a
b<
--> (?^msx:( . $ ..+ ))  matched : >a
bb
cc
<
--> (?^msx:( . $ .+ ))   matched : >c
<
4

1 に答える 1

9

バグです。perlbugコマンドラインも実行して報告してください。

$ perl -E'say "aa\nbb\ncc" =~ qr/( . $ .+ )/xms ? ">$1<" : 0'
0

$ perl -E'say "aa\nbb\ncc\n" =~ qr/( . $ .+ )/xms ? ">$1<" : 0'
>c
<

$ perl -v
...
This is perl 5, version 16, subversion 0 (v5.16.0) built for x86_64-linux
...

あなたが言ったように、それらはそれぞれ一致する必要が"a\nbb\ncc"あり"a\nbb\ncc\n"ます。に関連する最適化があります$/msそれらの1つは考慮に入れられなかったようです。


PS —あなたはに興味があるかもしれませんuse re 'debug';

$ perl -Mre=debug -E'say "aa\nbb\ncc" =~ qr/( . $ .+ )/xms ? ">$1<" : 0'
Compiling REx "( . $ .+ )"
Final program:
   1: OPEN1 (3)
   3:   SANY (4)
   4:   MEOL (5)
   5:   PLUS (7)
   6:     SANY (0)
   7: CLOSE1 (9)
   9: END (0)
anchored ""$ at 2 minlen 2 
Matching REx "( . $ .+ )" against "aa%nbb%ncc"
   0 <> <aa%nbb%ncc>         |  1:OPEN1(3)
   0 <> <aa%nbb%ncc>         |  3:SANY(4)
   1 <a> <a%nbb%ncc>         |  4:MEOL(5)
                                  failed...
   3 <aa%n> <bb%ncc>         |  1:OPEN1(3)
   3 <aa%n> <bb%ncc>         |  3:SANY(4)
   4 <aa%nb> <b%ncc>         |  4:MEOL(5)
                                  failed...
   6 <aa%nbb%n> <cc>         |  1:OPEN1(3)
   6 <aa%nbb%n> <cc>         |  3:SANY(4)
   7 <aa%nbb%nc> <c>         |  4:MEOL(5)
                                  failed...
Match failed
0
Freeing REx: "( . $ .+ )"
于 2012-07-10T15:34:23.947 に答える