perlの置換のこと

[上に] [前に] [次に]
和弘 2000/06/11(日) 17:26:42
aaabbbcccaaadddccc の中から bbb を取り出したいのですが、

s/aaa(.*)ccc/$1/ では bbbcccaaaddd になってしまいます。

最初に見つかった「閉じパターン」まででマッチングさせるにはどうしたらいいのでしょうか?
最後の/のあとに何か書けばいいと思うのですが・・・

S-pore [HomePage] 2000/06/11(日) 17:32:45
Perl5 なら,
(.*) → (.*?)
とすればええぢゃろう。

Perl4 ではどうやるのが一番いいですか?(便乗質問)

anno 2000/06/11(日) 17:48:49
/aaa([^c]*)ccc/
手元にPerl4ないから確認とれず。
日本語とか入っちゃうとダメだったような気も。

S-pore [HomePage] 2000/06/11(日) 17:53:50
> /aaa([^c]*)ccc/

これだと,"aaabcbccc" にマッチしてくれませんよね?

S-pore [HomePage] 2000/06/11(日) 18:22:08
私が考えたやつでは・・・

1 while (s|aaa(.*)|$1 =~ /ccc/; $` . $'|e);

これで,Perl5 の

s/aaa(.*?)ccc/$1/g;

と同じ動作をしてくれると思うんですが,
もっとエレガントな方法がないものか・・・。

Coo 2000/06/11(日) 18:24:11
cも抜きたいんだったらマッチした部分でさらにマッチングとか?

while (($a =~ /(ccc.*)ccc/)) {
$a = $1;
}
$a =~ s/ccc//;

効率悪そうだなぁ(笑)

S-pore [HomePage] 2000/06/11(日) 18:33:30
> 1 while (s|aaa(.*)|$1 =~ /ccc/; $` . $'|e);

おっと,これだと,"aaabbb" なんて場合まずいですね。
みゅぅ。(謎)

S-pore [HomePage] 2000/06/11(日) 18:42:20
1 while (s|aaa(.*)ccc|$a = $1; ($a =~ /ccc/) ? ($` . $' . 'ccc') : $a|eg);

なんかえらいことになってしまった。(^^;
もっと簡単な方法ないかなー。

S-pore [HomePage] 2000/06/11(日) 18:55:54
> aaabbbcccaaadddccc の中から bbb を取り出したいのですが、

というだけなら,

$_ = (/aaa/ && $' =~ /ccc/) ? $` : "";

でいけるんですけどねぇ・・・。

sadahiro 2000/06/11(日) 21:54:09
要するに "aaa" を開始タグ、"ccc" を終了タグとするのですね。
Perl4使ったことないのでなんですが、
本で "×4" と書いてないのだけ使ってみました。

$ini_tag="aaa";
$fin_tag="ccc";
$a ="aaabbbcccaaadddccc";
while ($a =~ m/$ini_tag/g) {
pos $a = $ini_pos = pos $a;
if ($a=~ m/$fin_tag/g){
  pos $a = $fin_pos = pos $a;
  push @matched, substr($a, $ini_pos, $fin_pos-$ini_pos-length $fin_tag);
} else {last}
}

sadahiro 2000/06/11(日) 22:08:07
追加。
pos $a = への代入は要らないようですね。

S-pore [HomePage] 2000/06/11(日) 22:19:08
pos って,Perl4 では使えなかったような・・・。

sadahiro 2000/06/11(日) 22:20:32
「取り出す」とは削除するということでしたか、失礼しました。

$ini_tag="aaa";
$fin_tag="ccc";
$a ="aaabbbcccaaadddccc";
if ($a =~ m/$ini_tag/g) {
  $ini_pos = pos $a;
if ($a=~ m/$fin_tag/g){
  $fin_pos = pos $a;
  $a = substr($a,0,$ini_pos) . substr($a, $fin_pos-length $fin_tag);
}
}

これで $a は "aaacccaaadddccc" になるのですが…

sadahiro 2000/06/11(日) 22:21:41
済みません、いずれにせよPerl4で確かめた訳ではないので.

おーなーしぇふ 2000/06/12(月) 01:23:23
>aaabbbcccaaadddccc の中から bbb を取り出したいのですが、

結果がどのようになればよいのかわかりにくいのですが(^^;)

「s/aaa(.*)ccc/$1/」を見る限り、aaabbbccc→bbbにしたいと
思うのですが、流れを見ると「削除」ということなので、
とりあえず「aaacccaaadddccc」という結果で良いなら:

いったんcccを「一文字」に置き換えて処理し、再度元に戻す
ようにすれば、うまくいくのではないかと……。

例)
$str = "aaabbbcccaaadddccc";
$tmp = "\t"; #タブ記号一文字で置き換え

$str =~ s/ccc/$tmp/g; #いったん置き換え
$str =~ s/(aaa)([^$tmp]*)($tmp)/$1$3/;
$str =~ s/$tmp/ccc/g; #置き換えを元に戻す

print "\$str:$str\n"; #結果表示


ちなみにaaaとcccで挟まれた文字列をすべて取り出すのなら、
つまり「ddd」も削除するなら、

$str =~ s/(aaa)([^$tmp]*)($tmp)/$1$3/g;

と、gを付けると良いです。

[上に] [前に] [次に]