3

私は今日このPerl構造に出くわしました:

@foo = split("\n", $bar);

これは、UNIXタイプの行末の場合は大きな文字列を行の配列に分割するのに適していますが、Windowsの場合は末尾に\rを残します。だから私はそれを次のように変更しました:

@foo = split("\r?\n", $bar);

これは文字列を行で分割し、末尾に\ rを残しません(ActivePerl 5.8でテスト済み)。それから、これはおそらく次のようになるはずだと私に指摘されました。

@foo = split(/\r?\n/, $bar);

では、なぜ2番目のバリアントがまったく機能するのでしょうか。二重引用符は、内容が評価されることを意味します。そのため、\rと\nは実際にはCRとLFとして扱われますが、?文字通りの疑問符ではなく、正規表現のメタ文字として扱われます。

正規表現の周りのスラッシュはsplit()のオプションですか?関数の最初のパラメーターが正規表現であると想定されているだけですか?

4

5 に答える 5

6

スラッシュは正規表現の標準的な区切り文字であり(他の式を使用できます)、二重引用符のように特殊文字とエスケープシーケンスを評価します。

編集:マニがコメントで説明したように、私はあまりにも速く撃った。もっと長い説明をしてみます:

通常、Perlで一致する正規表現はmで始まり、正規表現の本体は区切り文字で囲まれます。正規表現を照合するための標準の区切り文字はスラッシュmです。スラッシュを区切り文字として使用する場合は、先頭を省略できます。

m/\r?\n/
m"\r?\n"
m$\r?\n$
/\r?\n/

これらはすべて同じことを行い、「正規表現リテラル」と呼ばれます。一重引用符を使用すると、エスケープシーケンスは評価されません。

この時点で、二重引用符で囲まれているが先頭がない最初の試みがmまったく機能したのは奇妙に思えますが、Arnsheaが説明しsplitたように、正規表現をリテラルとしてだけでなく受け入れるという点で特殊なケースです。文字列としても。

于 2009-02-24T00:59:56.307 に答える
6

split 正規表現を文字列または正規表現リテラルとして渡すことができます。したがって、二重引用符で囲まれた文字列として渡すことは問題ありません。

標準の /regex/ 以外の文字で正規表現リテラルを区切ることもできます

于 2009-02-24T03:09:47.930 に答える
5

はい、split は常に正規表現を取ります (単一のスペースを含む文字列の特殊なケースを除く)。文字列を指定すると、正規表現として使用されます。=~ でも同じことが起こります (例: $foo =~ "pattern")。また、正規表現のメタ文字は、// の使用に関係なく、そのように扱われます。

誤って split("|", "a|b|c") を試行しないように、常に // を使用して、リテラル文字列や正規表現ではないことを強調することをお勧めします。いつか。

于 2009-02-24T05:14:26.647 に答える
1

いくつかの選択肢のベンチマークを見てみましょう。

use Modern::Perl;
use Benchmark qw'cmpthese';

# set up some test data
my $bar = join "\n", 'a'..'z';

my $qr  = qr/\r?\n/;
my $str =   "\r?\n";
my $qq  = qq/\r?\n/;

my %test = (
  '   //' =>   sub{ split(   /\r?\n/, $bar ); },
  '  m//' =>   sub{ split(  m/\r?\n/, $bar ); },
  '  m""' =>   sub{ split(  m"\r?\n", $bar ); },
  ' qr//' =>   sub{ split( qr/\r?\n/, $bar ); },
  ' qq//' =>   sub{ split( qq/\r?\n/, $bar ); },
  '   ""' =>   sub{ split(   "\r?\n", $bar ); },
  '$qr  ' =>   sub{ split( $qr,  $bar ); },
  '$str ' =>   sub{ split( $str, $bar ); },
  '$qq  ' =>   sub{ split( $qq,  $bar ); }
);

cmpthese( -5, \%test, 'auto');
ベンチマーク:実行中    
    ""、//、m ""、m //、qq //、qr //、$ qq、$ qr、$ str  
    少なくとも5CPU秒の間..

      "":6ウォールクロック秒(5.21 usr + 0.02 sys = 5.23 CPU)@ 42325.81 / s(n = 221364)
      //:6ウォールクロック秒(5.26 usr + 0.00 sys = 5.26 CPU)@ 42626.24 / s(n = 224214)
     m "":6ウォールクロック秒(5.30 usr + 0.01 sys = 5.31 CPU)@ 42519.96 / s(n = 225781)
     m //:6ウォールクロック秒(5.20 usr + 0.00 sys = 5.20 CPU)@ 42568.08 / s(n = 221354)
    qq //:6ウォールクロック秒(5.24 usr + 0.01 sys = 5.25 CPU)@ 42707.43 / s(n = 224214)
    qr //:6ウォールクロック秒(5.11 usr + 0.03 sys = 5.14 CPU)@ 33277.04 / s(n = 171044)
   $ qq:5ウォールクロック秒(5.15 usr + 0.00 sys = 5.15 CPU)@ 42154.76 / s(n = 217097)
   $ qr:4ウォールクロック秒(5.28 usr + 0.00 sys = 5.28 CPU)@ 39593.94 / s(n = 209056)
   $ str:6ウォールクロック秒(5.29 usr + 0.00 sys = 5.29 CPU)@ 41843.86 / s(n = 221354)


         レートqr//$ qr $ str $ qq "" m "" m // // qq //
 qr // 33277 / s---16%-20%-21%-21%-22%-22%-22%-22%
$ qr 39594 / s 19%---5%-6%-6%-7%-7%-7%-7%
$ str 41844 / s 26%6%---1%-1%-2%-2%-2%-2%
$ qq 42155 / s 27%6%1%---0%-1%-1%-1%-1%
   "" 42326 / s 27%7%1%0%---0%-1%-1%-1%
  m "" 42520 / s 28%7%2%1%0%---0%-0%-0%
  m // 42568 / s 28%8%2%1%1%0%---0%-0%
   // 42626 / s 28%8%2%1%1%0%0%---0%
 qq // 42707 / s 28%8%2%1%1%0%0%0%-

これらはすべて基本的に同じ速度であり、qr//わずかに遅いことが示されていることに注意してください。このテストを数回実行した後、qr//常に$qr最も遅く、2番目に遅いものでした。他の人と定期的に場所を交換します。

したがって、基本的には、の正規表現をどのように設定するかは重要ではありません  split()

于 2009-02-24T18:29:39.530 に答える
0

split("\r?\n", $bar)単に間違っています。split組み込み関数は、パターンとして指定された正規表現を想定しています。で分割するためのperlマニュアルを読んでくださいperldoc -f split

したがって、のみを使用してsplit(/\r?\n/, $bar)ください。

于 2012-01-15T19:02:44.330 に答える