2004年10月20日

いつも探してしまうperlでのファイル内文字列置換(その2)

perl -pi.bak -e 's/変換前文字列/変換後文字列/g' 対象file(s)
だと、変改前文字列が複数行にわたるときにうまくいかない。
s///mとかs///sとかつけてやってみたけど、だめだった。

perldoc perlrunでもう一度よく見てみると、

       -p   causes Perl to assume the following loop around your
            program, which makes it iterate over filename argu-
            ments somewhat like sed:

              LINE:
                while (<>) {
                    ...             # your program goes here
                } continue {
                    print or die "-p destination: $!\n";
                }

            If a file named by an argument cannot be opened for
            some reason, Perl warns you about it, and moves on to
            the next file.  Note that the lines are printed auto-
            matically.  An error occurring during printing is
            treated as fatal.  To suppress printing use the -n
            switch.  A -p overrides a -n switch.

            "BEGIN" and "END" blocks may be used to capture con-
            trol before or after the implicit loop, just as in
            awk.
そうかぁ、一行ずつ読み込むのだからだめなのね。

結局、全部の行を読み込んでやると言うことで、

#!/usr/bin/perl

$aft ='top-line
あーだこーだ。
なんだかんだ。
bottom-line';

my $all_data = '';
while(<>){
	$all_data .= $_;
}

$all_data =~ s/top-line\nbottom-line/$aft/sg;

open(ARGVOUT,">$ARGV");
select(ARGVOUT);
print $all_data ;
close(ARGVOUT);
てなことをやる羽目に。
これで、
top-line
bottom-lne
という特定の2行組み合わせの間に所望の行を挟み込むことができる。

しかし、某師匠により、ワンライナーを救う別解を教えてもらえた。

単純に \n でマッチすれば良いのならば

$ echo -n "aaaa\nbbbb\n" | perl -0pe 's/aaaa\nbbbb/match/'
match

でもイケます。\n 以外はマッチさせず! ということならば /s や /m は副作用があるので使わん方が良いと思います。用途によると思いますが。

> なお,この正規表現を使うには,事前に undef $/ としてレコードセパレータ
> を無効にしておく必要があります。
> 
> ワンライナーだったら -0 です。
さすが師匠。だてに眉が濃いわけではない(。。)\バキッ☆

投稿者 his : 2004年10月20日 02:56
このエントリーのトラックバックURL: http://hoop.euqset.org/blog/mt-tb2006.cgi/721
perl でズバッと置換
概要 カレントディレクトリの全ての HTML ファイルの中の全ての文字列 abc を ...
ウェブログ: JE no hitori chat
時刻: 2005年7月26日 00:07
コメント
コメントする









名前、アドレスを登録しますか?





画像の中に見える文字を入力してください。