1. ホーム
  2. ruby

[解決済み] 変数名を使ったRubyの正規表現

2022-10-25 02:50:25

質問

Rubyで変数名の値を元にした正規表現パターンを作成/使用することは可能でしょうか?

例えば、Rubyの文字列で以下のようなことができるのは皆さんご存知だと思います。

str = "my string"
str2 = "This is #{str}" # => "This is my string"

正規表現で同じことをしたいのですが。

var = "Value"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "a test foo"

明らかに、これはリスト通りに動作しません。私は、私がやりたいことを示す例として、それをそこに置いただけです。 私は変数の内容の値に基づいて正規表現でマッチする必要があります。

どのように解決するのですか?

動かないと思っていたコードが動きます。

var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' )   # => "a test foo"

もし var が正規表現のメタ文字を含むことができれば、さらに面白いことが起こります。 もしそうで、それらのメタ文字が通常正規表現で行うことを行いたいのであれば、同じ gsub が動作します。

var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"

ただし、検索文字列にメタキャラクタが含まれていて ではなく をメタ文字として解釈したい場合は、以下のように Regexp.escape を使用します。

var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"

あるいは、gsubに正規表現ではなく文字列を与えるだけです。 MRI >= 1.8.7では、gsubは文字列置換の引数を正規表現ではなく、プレーンな文字列として扱います。

var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"

(以前は、gsubの文字列置換の引数は自動的に正規表現に変換されていました。 1.6でそうなっていたのは知っています。 どのバージョンで変更されたかは覚えていません)。

他の回答にもあるように、補間の代わりとしてRegexp.newを使うことができます。

var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"