6

私はついにファイルの各行の終わりにテキストを追加する方法を理解しました:

perl -pe 's/$/addthis/' myfile.txt

ただし、正規表現を頻繁に使用するためにPerlを学習しようとしているため、次のperlコマンドが各行の末尾と先頭に「addthis」というテキストを追加する理由がわかりません。

perl -pe 's/$/addthis/g' myfile.txt

正規表現の一致にどの修飾子が使用されていても、「$」は行の終わりに一致すると思いましたが、これは間違っていると思いますか?

4

3 に答える 3

11

要約: あなたがしていることについては、改行の/gにのみ一致するようにドロップしてください。は、改行の前文字列の最後(改行の後)で一致するように指示しています。/g

/m修飾子がない$場合、改行の前(文字列の最後にある場合)または文字列の最後のいずれかに一致します。たとえば、との両方を使用する"foo""foo\n"、は。の$後に一致しfooます。ただし、を使用すると、埋め込まれた改行が文字列の最後にないため、の"foo\nbar"後に一致します。bar

モディファイアを使用すると、一致する/gすべての場所を取得できます。$

s/$/X/g;

のような行を取り、"foo\n"それをに変換し"fooX\nX"ます。

サイドバー:/m修飾子を使用すると、文字列の終わりの前に発生する改行を一致させること ができるため$

s/$/X/mg;

に変換"foo\nbar\n"され"fooX\nbarX\nX"ます。

于 2013-02-18T16:36:54.407 に答える
5

Jim Davisが指摘したように、文字列の終わり、または文字の前(オプション付き)の両方に一致$\nます/m。(perlre Perldocページの「正規表現」セクションを参照してください。修飾子を使用すると、照合を続行できます。g

複数行のPerl正規表現(つまり、行末に1回だけ出現する場合でも、改行文字を含むPerl正規表現)は、ほとんどのPerlプログラマーが処理に問題を抱えるあらゆる種類の複雑さを引き起こします。

  • 一度に1行ずつファイルを読み取る場合は、その行で何かchompを行う前に必ず使用してください。これにより、修飾子を使用する際の問題が解決されます。g

  • Windowsから提供されたLinux/Macでファイルを読み取っている場合は、さらに問題が発生する可能性があります。その場合、\r\n文字の両方があります。プログラムをデバッグしようとして最近わかったように、\r文字はによって削除されませんchomp。私は今、常にテキストファイルを開いて読むようにしています

このような:

open my $file_handle, "<:crlf", $file...

これは、これが実際にLinux / Macシステム上のWindowsファイルである場合にのみ、\r\n文字を自動的に置き換えます。\nこれが通常のLinux/Macテキストファイルの場合、何もしません。他の明白な解決策は、Windowsを使用しないことです(リムショット!)。

もちろん、あなたの場合、最初にchompを使用すると、次のようになります。

$cat file
line one
line two
line three
line four
$ perl -pe 'chomp;s/$/addthis::/g`
line oneaddthis::line twoaddthis::line threeaddthis::line fouraddthis::

チョップがを削除した\nので、行が印刷されたときに表示されなくなりました。うーん...

$ perl -pe 'chomp;s/$/addthis/g;print "\n";
line oneaddthis
line twoaddthis
line threeaddthis
line fouraddthis

それはうまくいきます!そして、あなたのワンライナーはほんの少し理解できないだけです。


もう1つは、DamianConwayが著書PerlBestPracticesの第12章で推奨しているより現代的なアプローチを取ることです。

\Aおよび\zを文字列境界アンカーとして使用します。

常に/mを使用するという以前の方法を採用していなくても、デフォルトの意味で^と$を使用することはお勧めできません。確かに、Perl正規表現1で^と$が実際に何を意味するかはご存知でしょう。しかし、あなたのコードを読んだり維持したりする人は知っていますか?それとも、前述の方法でそれらのメタ文字を誤解する可能性が高いですか?Perlは、常に「文字列の開始」と「文字列の終了」を意味するマーカーを提供します:\Aと\z(大文字のA、ただし小文字のz)。/ mがアクティブであるかどうかに関係なく、「文字列の開始/終了」を意味します。読者が^と$の意味に関係なく、「文字列の開始/終了」を意味します。

Conawayのアドバイスに従い、これを行った場合:

perl -pe 's/\z/addthis/mg' myfile.txt

addthisフレーズがすべての行の最後にのみ追加されていることがわかります。

$cat file
line one
line two
line three
line four
$ perl -pe `s/\z/addthis/mg` myfile.txt
line one
addthisline two
addthisline three
addthisline four
addthis

それがどれほどうまく機能するかを見てください。それaddthisが各行の最後に追加されました!\n...その行の文字の直後。

十分に楽しんで、仕事に戻ります。(待ってください、それは大統領の日です。それは有給休暇です。もちろん、火曜日の朝までに私が約束したすべてのことを除いて、今日は仕事はありません)。

これが、正規表現がどれほど楽しいか、そしてなぜ多くの人がPythonを学ぶことにしたのかを理解するのに役立つことを願っています。


1. Perlで何を意味し^、実際に意味するのかを知っていますか?$ええと、もちろんそうです。私は数十年の間Perlでプログラミングしてきました。うん、私はこれらすべてのものを知っています。(自己メモ:$どうやら私がいつも思っていた意味ではありません。)

于 2013-02-18T17:32:45.377 に答える
0

回避策:

perl -pe 's/\n/addthis\n/' 

修飾子は不要g:正規表現は行ごとに扱われます。

于 2013-02-18T16:39:11.493 に答える