2017-01-13 5 views
2

文字と数字が交互に並んでいます。私は各文字をそれに先行する文字数で置き換えたい。たとえば、2a3baabbbを返します。ルビー正規表現のスキャンとgsubは、ブロック内のキャプチャグループとは異なる働きをします。

まず、私が行う場合:

"2a3b".scan(/(\d)(.)/) do |count, char| 
    puts char * count.to_i 
end 

私が手に:私がしなければ、

aa 
bbb 

しかし:

"2a3b".gsub(/(\d)(.)/) do |count, char| 
    char * count.to_i 
end 

私はエラーを取得する:

NoMethodError: undefined method `*' for nil:NilClass 

どちらも同じように動作してはいけませんか?(アップデート:キャプチャグループをブロックパラメータとして受け入れますか?

更新:(回避策、動作)

"2a3b".gsub(/(\d)(.)/) do |match| 
    $2 * $1.to_i 
end 

戻り値:

"aabbb" 

予想通り。

+0

私は両方のアプローチが本当に好きです。しかし、私は「アップデート」が不要であると感じています。また、以下の回答を減らすので、元の質問に戻すのが最良です。 –

+0

@ sagarpandya82最初の更新は、ある回答が私の質問を完全に誤解しているため、私の意図を明確にしています。 2回目の更新は、最初の回答が来る前に行われました。 – Anand

+1

この[リンク](http://batsov.com/articles/2013/08/30/using-gsub-with-a-block/)はうまく言っています。*一部の人々は、gsubがすべての一致するグループを引数として指定します。そうでない場合は、正規表現全体を表す単一の引数が常に得られます。* – Anand

答えて

5

いいえ、同じ動作をしません。 gsubのブロック形式は1つのパラメータしか受け付けないため、2番目のパラメータはnilになります。したがって、エラーが発生します。 使用のhttp://ruby-doc.org/core-2.1.4/String.html#method-i-gsub

例を参照してください:"hello".gsub(/./) {|s| s.ord.to_s + ' '}

In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $' will be set appropriately. The value returned by the block will be substituted for the match on each call.

The result inherits any tainting in the original string or any supplied replacement string.

+0

ええ、元の質問を回避策で編集しました。私は最良の選択肢はブロック内のマッチを使用することだと思います。 – Anand

0

をいいえ、彼らは二つの異なる方法であり、異なることを行います。

が抽象的でhttp://ruby-doc.org/core-2.2.2/String.html#gsub-methodhttp://ruby-doc.org/core-2.2.2/String.html#scan-method

を参照してくださいGSUBがでパターンに置換を行うことについての詳細である一方で、スキャンが(何らかの方法でそれらをフォーマットし、ブロックで)、文字列/式の中でパターンを見つけるためのより多くのです文字列。

関連する問題