こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

正規表現での置き換え

正規表現置き換えについて

-----入力 -----
a (b)
B (C)
test.csv file.dat
-----出力 -----
b (a)
C (B)
file.csv test.dat
---------------
としたくて以下のコードを書いたのですが
実際の出力が
$2 ($1)
$2 ($1)
$2.csv $1.dat
となってしまいます。

--以下ソース
%Convert = (
'(.+) \\((.+)\\)','$2 ($1)'
,'(.+)\\.csv (.+)\\.dat','$2.csv $1.dat'
);

while(<DATA>){
foreach $key ( keys %Convert ){
s/$key/$Convert{$key}/gi;
}
print;
}
__DATA__
a (b)
B (C)
test.csv file.dat

投稿日時 - 2008-02-26 15:00:18

QNo.3811443

困ってます

質問者が選んだベストアンサー

正規表現の置換部を2回ダブルクォート文字列として評価するとうまくいきます。

%Convert = (
'(.+) \\((.+)\\)', '$2 ($1)'
,'(.+)\\.csv (.+)\\.dat', '$2.csv $1.dat'
);

while(<DATA>){
foreach $key ( keys %Convert ){
s/$key/"\"$Convert{$key}\""/giee;
}
print;
}
__DATA__
a (b)
B (C)
test.csv file.dat

1回目の評価で置換部は "$2 ($1)" となり、2回目の評価で $2 と $1 がそれぞれ置き換えられます。

投稿日時 - 2008-02-27 00:00:57

ANo.4

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

なんとなく別解。

require 5.008;
use strict;


my %Convert = (
# '(.+) \\((.+)\\)', '$2 ($1)'
# ,'(.+)\\.csv (.+)\\.dat', '$2.csv $1.dat'
'(.+) \\((.+)\\)', '%2$s (%1$s)'
,'(.+)\\.csv (.+)\\.dat', '%2$s.csv %1$s.dat'
);

while(<DATA>){
foreach my $key ( keys %Convert ){
#s/$key/$Convert{$key}/gi;
s/$key/sprintf $Convert{$key}, $1, $2/gie;
}
print;
}


__DATA__
a (b)
B (C)
test.csv file.dat

データをちょっといじってますが、

b (a)
C (B)
file.csv test.dat

となります。

投稿日時 - 2008-02-27 00:42:02

ANo.3

ん~, 手元で実験した限りでは, 2つ目は
'(.+)\\.csv (.+)\\.dat', '"$2.csv $1.dat"'
でいいような気がしますが....>#2.
まあ, 確かにちょっと面倒かも.

投稿日時 - 2008-02-26 18:09:14

ANo.2

すみません。確認したら#1ではだめですね。

my %Convert = (
'(.+) \\((.+)\\)', '"$2 ($1)"'
,'(.+)\\.csv (.+)\\.dat', '"$2" . "csv" . " $1" . ".dat"'
);

while(<DATA>){
foreach my $key (keys %Convert){
s/$key/$Convert{$key}/giee;
}
print;
}
__DATA__
a (b)
B (C)
test.csv file.dat

元データの定義が面倒なのと、evalが2回必要です。

#たぶん使いまわせるモジュールがあると思いますが

投稿日時 - 2008-02-26 16:38:09

ANo.1

evaってください。
s/$key/$Convert{$key}/gi;
}

s/$key/$Convert{$key}/gie;
}

たぶんこれで。

投稿日時 - 2008-02-26 15:27:56

あなたにオススメの質問