[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Strange behavior of String.scan

Alex Young

5/27/2007 8:17:00 AM

HÃ¥vard Moen wrote:
> When I use String.scan with a block and just one group the result ends
> up as an array. More than one group works as expected. A small example to
> demonstrate:
>
> --ruby code start--
> data = ' lb method member observed
> monitor all http
> member 192.168.1.68:http'
> data.scan(/monitor all (.*)$/) do |monitor|
> puts monitor.inspect
> end
> data.scan(/member ([0-9.]+):(.*)/) do |adress, port|
> puts adress.inspect
> puts port.inspect
> end
> --ruby code end--
>
> gives me:
> ["http"]
> "192.168.1.68"
> "http"

That's expected. What scan actually yields to the block is an array,
and in your second example that array is being automatically split into
its component parts because you've given more than one block parameter
in the pipes. A third example should make it clear:

irb(main):004:0> data.scan(/member ([0-9.]+):(.*)/) do |match|
irb(main):005:1* puts match.inspect
irb(main):006:1> end
["192.168.1.68", "http"]

--
Alex

5 Answers

Daniel DeLorme

5/27/2007 9:21:00 AM

0

HÃ¥vard Moen wrote:
> Ok, but is there a way to get just the string without using something
> like monitor = monitor[0] at the start of the block?

You can use a comma to force the array to be parallel-assigned instead
of single-assigned:

data.scan(/monitor all (.*)$/) do |monitor,|
puts monitor.inspect
end

Daniel

Robert Klemme

5/27/2007 9:22:00 AM

0

On 27.05.2007 10:17, Alex Young wrote:
> Håvard Moen wrote:
>> When I use String.scan with a block and just one group the result ends
>> up as an array. More than one group works as expected. A small example
>> to demonstrate:
>>
>> --ruby code start--
>> data = ' lb method member observed
>> monitor all http
>> member 192.168.1.68:http'
>> data.scan(/monitor all (.*)$/) do |monitor|
>> puts monitor.inspect
>> end
>> data.scan(/member ([0-9.]+):(.*)/) do |adress, port|
>> puts adress.inspect
>> puts port.inspect
>> end
>> --ruby code end--
>>
>> gives me:
>> ["http"]
>> "192.168.1.68"
>> "http"
>
> That's expected. What scan actually yields to the block is an array,
> and in your second example that array is being automatically split into
> its component parts because you've given more than one block parameter
> in the pipes. A third example should make it clear:
>
> irb(main):004:0> data.scan(/member ([0-9.]+):(.*)/) do |match|
> irb(main):005:1* puts match.inspect
> irb(main):006:1> end
> ["192.168.1.68", "http"]

irb(main):001:0> "abc".scan(/abc/) {|m| p m}
"abc"
=> "abc"
irb(main):002:0> "abc".scan(/(a)bc/) {|m| p m}
["a"]
=> "abc"
irb(main):003:0> "abc".scan(/(a)(b)c/) {|m| p m}
["a", "b"]
=> "abc"

robert

Håvard Moen

5/27/2007 9:44:00 AM

0

Alex Young <alex@blackkettle.org> wrote:
> HÃ¥vard Moen wrote:
>> When I use String.scan with a block and just one group the result ends
>> up as an array. More than one group works as expected. A small example to
>> demonstrate:
>>
>> --ruby code start--
>> data = ' lb method member observed
>> monitor all http
>> member 192.168.1.68:http'
>> data.scan(/monitor all (.*)$/) do |monitor|
>> puts monitor.inspect
>> end
>> data.scan(/member ([0-9.]+):(.*)/) do |adress, port|
>> puts adress.inspect
>> puts port.inspect
>> end
>> --ruby code end--
>>
>> gives me:
>> ["http"]
>> "192.168.1.68"
>> "http"
>
> That's expected. What scan actually yields to the block is an array,
> and in your second example that array is being automatically split into
> its component parts because you've given more than one block parameter
> in the pipes. A third example should make it clear:
>
> irb(main):004:0> data.scan(/member ([0-9.]+):(.*)/) do |match|
> irb(main):005:1* puts match.inspect
> irb(main):006:1> end
> ["192.168.1.68", "http"]
>

Ok, but is there a way to get just the string without using something
like monitor = monitor[0] at the start of the block?

--
HÃ¥vard
Laws are like sausages, it is better not to see them being made.
-- Bismarck

Håvard Moen

5/27/2007 10:41:00 AM

0

Daniel DeLorme <dan-ml@dan42.com> wrote:
> HÃ¥vard Moen wrote:
>> Ok, but is there a way to get just the string without using something
>> like monitor = monitor[0] at the start of the block?
>
> You can use a comma to force the array to be parallel-assigned instead
> of single-assigned:
>
> data.scan(/monitor all (.*)$/) do |monitor,|
> puts monitor.inspect
> end

Great, thanks.

--
HÃ¥vard
Laws are like sausages, it is better not to see them being made.
-- Bismarck

Robert Klemme

5/27/2007 11:25:00 AM

0

On 27.05.2007 11:44, Håvard Moen wrote:
> Alex Young <alex@blackkettle.org> wrote:
>> Håvard Moen wrote:
>>> When I use String.scan with a block and just one group the result ends
>>> up as an array. More than one group works as expected. A small example to
>>> demonstrate:
>>>
>>> --ruby code start--
>>> data = ' lb method member observed
>>> monitor all http
>>> member 192.168.1.68:http'
>>> data.scan(/monitor all (.*)$/) do |monitor|
>>> puts monitor.inspect
>>> end
>>> data.scan(/member ([0-9.]+):(.*)/) do |adress, port|
>>> puts adress.inspect
>>> puts port.inspect
>>> end
>>> --ruby code end--
>>>
>>> gives me:
>>> ["http"]
>>> "192.168.1.68"
>>> "http"
>> That's expected. What scan actually yields to the block is an array,
>> and in your second example that array is being automatically split into
>> its component parts because you've given more than one block parameter
>> in the pipes. A third example should make it clear:
>>
>> irb(main):004:0> data.scan(/member ([0-9.]+):(.*)/) do |match|
>> irb(main):005:1* puts match.inspect
>> irb(main):006:1> end
>> ["192.168.1.68", "http"]
>>
>
> Ok, but is there a way to get just the string without using something
> like monitor = monitor[0] at the start of the block?

Use only capturing groups for what you want to capture. For all others
use non capturing groups. This sounds trivial but it's actually as easy
as that. :-)

In case you haven't seen non capturing groups yet:

irb(main):002:0> "cababab".scan(/(.)(?:ab)+/) {|m| p m}
["c"]
=> "cababab"

Kind regards

robert