sub(pattern, replace) -> String
[permalink][rdoc]文字列中で pattern にマッチした最初の部分を文字列 replace で置き換えた文字列を生成して返します。
置換文字列 replace 中の \& と \0 はマッチした部分文字列に、 \1 ... \9 は n 番目の括弧の内容に置き換えられます。置換文字列内では \`、\'、\+ も使えます。これらは $`、$'、$+ に対応します。
p 'abcdefg'.sub(/def/, '!!') # => "abc!!g"
p 'abcabc'.sub(/b/, '<<\&>>') # => "a<<b>>cabc"
p 'xxbbxbb'.sub(/x+(b+)/, 'X<<\1>>') # => "X<<bb>>xbb"
注意:
第 2 引数 replace に $1 を埋め込んでも意図した結果にはなりません。この文字列が評価される時点ではまだ正規表現マッチが行われておらず、 $1 がセットされていないからです。
また、sub では「\」が部分文字列との置き換えという特別な意味を持つため、 replace に「\」自身を入れたいときは「\」を二重にエスケープしなければなりません。
p 'xbbb-xbbb'.sub(/x(b+)/, "#{$1}") # => "-xbbb" # NG
p 'xbbb-xbbb'.sub(/x(b+)/, "\1") # => "1-xbbb" # NG
p 'xbbb-xbbb'.sub(/x(b+)/, "\\1") # => "bbb-xbbb" # OK
p 'xbbb-xbbb'.sub(/x(b+)/, '\1') # => "bbb-xbbb" # OK
p 'xbbb-xbbb'.sub(/x(b+)/, '\\1') # => "bbb-xbbb" # OK
puts '\n'.sub(/\\/, "\\\\") # => \n # NG
puts '\n'.sub(/\\/, '\\\\') # => \n # NG
puts '\n'.sub(/\\/, "\\\\\\\\") # => \\n # OK
puts '\n'.sub(/\\/, '\\\\\\\\') # => \\n # OK
このような間違いを確実に防止し、コードの可読性を上げるには、 \& や \1 よりも下記のようにブロック付き形式の sub を使うべきです。
p 'xbbb-xbbb'.sub(/x(b+)/) { $1 } # => "bbb-xbbb" # OK
puts '\n'.sub(/\\/) { '\\\\' } # => \\n # OK
[SEE_ALSO] String#gsub
sub(pattern) {|matched| .... } -> String
[permalink][rdoc]文字列中で pattern にマッチした最初の部分をブロックに渡し、その評価結果で置き換えた新しい文字列を返します。ブロックなしの sub と違い、ブロックの中からは組み込み変数 $1, $2, $3, ... を問題なく参照できます。
p 'abcabc'.sub(/b/) {|s| s.upcase } #=> "aBcabc"
p 'abcabc'.sub(/b/) { $&.upcase } #=> "aBcabc"
[SEE_ALSO] String#gsub
sub(pattern, hash) -> String
[permalink][rdoc]文字列中の pattern にマッチした部分をキーにして hash を引いた値で置き換えます。
hash = {'b'=>'B', 'c'=>'C'}
p "abcabc".sub(/[bc]/){hash[$&]} #=> "aBCabc"
p "abcabc".sub(/[bc]/, hash) #=> "aBCabc"