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 です。


さすが師匠。だてに眉が濃いわけではない(。。)\バキッ☆


0 件のコメント:

コメントを投稿