简体   繁体   中英

ruby regex scan and gsub work differently with capture groups in blocks

I have a string of alternating digits and letters. I want to replace each character with the number of letters preceding it. For example, 2a3b should return aabbb .

First, If I do:

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

I get:

aa
bbb

But, if I do:

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

I get an error:

NoMethodError: undefined method `*' for nil:NilClass

Shouldn't they both behave the same (Update: I mean, accept capture groups as block params)?

Update : (workaround, which works)

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

returns:

"aabbb"

as expected.

No they don't behave the same. The block form of gsub only accepts one parameter, so the second is going to be nil, hence your error. See http://ruby-doc.org/core-2.1.4/String.html#method-i-gsub

Example of use: "hello".gsub(/./) {|s| s.ord.to_s + ' '} "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.

No, they are two different methods and do different things.

See http://ruby-doc.org/core-2.2.2/String.html#gsub-method and http://ruby-doc.org/core-2.2.2/String.html#scan-method

In the abstract, scan is more for finding patterns in strings/expressions, (and with a block, formatting them in some way) while gsub is more about doing replacements on patterns in a string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM