検索と置換のためにSQL文の一部を抽出する方法は?

検索と置換のためにSQL文の一部を抽出する方法は?

bashシェルを使用して検索と置換を試みています。次の行を含むファイルがあります。

...
INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '฿');
...

各行を次に変換したいと思います。

currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')

ご覧のように、INSERT SQLコマンドから2番目のパラメータを抽出しました。私は私ができると思いました。

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb

しかし、何も起こりません。つまり、置き換えられた出力はラインを変更せずに残します。 SQL文で2番目の値をキャプチャし、その値から新しい行を作成する方法は?

ベストアンサー1

交換された出力はラインを変更せずに残します。

これは、正規表現が入力と一致しないことを示します。したがって、一歩下げて動作する最小正規表現を得ることができるかどうかを見てみましょう。

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

交換部品を取り外すことは、当然、元々購入した部品と差がなく、入力と一致しません。

正規表現の最後の部分には、正規表現('(.*?)', '(.*?)', '(.*?)')で特別な意味を持つ文字割り当てが含まれているので、それを削除して機能するかどうかを見てみましょう。

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES .*;//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

まだ一致するものはありません。今、唯一の特殊文字は()エスケープする必要がある文字だけです。

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES .*;//" currencies.rb
> 

はい、一致します。入力が一致して削除されたため、末尾のビットを再び追加し、今回は他のビットも()エスケープします。

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb
> 

それでも一致するので、代替アイテムをもう一度追加してみましょう。

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
> currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')

うーん、間違った部分が一致しているようです。これは、&が目的の個々のサブグループではなく完全一致表現に置き換えられるためです$1$2

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$2) || Currency.new(:code => '\$2')/" currencies.rb
> currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')

ほとんどそこにいくつかの引用符がありません。他の2つのサブグループも一致する必要はないので、削除します。

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\$1') || Currency.new(:code => '\$1')/" currencies.rb 
> currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')

それが私たちが望んでいたものです。

うまくいかないように見える複雑な正規表現に直面すると、通常は言語やツールごとに異なる特殊文字の問題です。時にはエスケープが必要な場合もありません。正確に必要な部分ではなくても、入力の一部と一致する正規表現が得られるまで、最初により単純な代替方法を使用してその文字を削除するのに役立ちます。その後、そこで少しずつ作業します。リラックスしたり、欲しいものを手に入れましょう。この問題が発生した場合は、使用している言語/ツールのマニュアルを読んで、実際に必要な構文が何であるかを調べる必要があります。

おすすめ記事