# Ruby global regex question

**URL:** <https://www.ruby-forum.com/t/ruby-global-regex-question/153582>\
**Category:** Ruby\
**Created:** [November 19, 2008, 1:10am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582 "2008-11-19T01:10:58Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 1:10am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/1 "2008-11-19T01:10:58Z")

</div>

For the life of me, i can’t figure out a ruby equivalent to perl’s /g

basically, i want to do the following

while htmlSource=~m/

(.\*?)\<\table\>/g do  
tableSource=$1  
tableSource=~m/Index (\d+)/  
indexNumber=$1

while tableSource=~m/

(.\*?)\</tr\>/g do  
tableRowSource=$1  
doSomethingWith(tableRowSource, indexNumber)  
end#while tableSource

end#while htmlSource

I will actually need to pull multiple vars, not just a single one,  
from the regex  
I will need to do the outer loop an unknown amount of times per  
document (0-20) and i will need to loop the inner an unknown amount of  
times (0-29)

Thread safe would be a plus.

any suggestions?

|
| |

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 1:41am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/2 "2008-11-19T01:41:58Z")

</div>

On Tue, Nov 18, 2008 at 4:06 PM, knohr [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> while tableSource=~m/(.\*?)\</tr\>/g do  
> document (0-20) and i will need to loop the inner an unknown amount of  
> times (0-29)
> 
> Thread safe would be a plus.
> 
> any suggestions?

I think this does what you want, although I don’t think gsub was really  
made  
for this purpose.

def doSomethingWith(s)  
print s, “\n”  
end

htmlSource = ‘

1,11,2

|
| |
|
| |

’  
htmlSource \<\< ‘2,11,2

|
| |
|
| |

’

htmlSource.gsub(/

(._?)\</table\>/) do |t|  
tableRowSource = $1  
tableRowSource.gsub(/__(._?)\</tr\>/) do |r|  
doSomethingWith $1  
end  
end

|
| |

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 3:04am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/3 "2008-11-19T03:04:58Z")

</div>

On 2008.11.19., at 1:06, knohr wrote:

> while tableSource=~m/(.\*?)\</tr\>/g do  
> document (0-20) and i will need to loop the inner an unknown amount of  
> times (0-29)
> 
> Thread safe would be a plus.
> 
> any suggestions?

While I can’t answer your original question, I could possibly help you  
with the scraping if you are willing to reveal the page you are trying  
to scrape and the data bits on it which should be scraped.

Cheers,  
Peter

* * *

[http://www.rubyrailways.com](http://www.rubyrailways.com)  
[http://scrubyt.org](http://scrubyt.org)

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 4:22am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/4 "2008-11-19T04:22:16Z")

</div>

On Nov 18, 7:08 pm, knohr [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> tableRowSource=$1
> 
> ```
> 
> Thread safe would be a plus.

Would fast be a plus? No nested loop?

require ‘nokogiri’  
doc = Nokogiri::HTML(htmlSource)  
doc.search(‘//tr’).each do |row|  
index = row.xpath(‘ancestor::table/\*[contains(“Index”,.)]’)  
doSomethingWith(row.text,index[/(\d)/])  
end

The location of the element containing the index may have to be  
modified.

– Mark.

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 7:12am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/5 "2008-11-19T07:12:25Z")

</div>

On 19.11.2008, at 00:37 , Alan Johnson wrote:

> > tableSource=~m/Index (\d+)/  
> > I will actually need to pull multiple vars, not just a single one,  
> > any suggestions?  
> > htmlSource = ‘
> > 
> > 1,11,2
> > 
> > |
> > | |
> > |
> > | |
> > 
> > ’  
> > Alan  
> > That is pretty much how, except globals are hardly thread safe I  
> > think. Use scan instead of gsub:  
> > Here’s something I wrote to extract information from data structured  
> > like this:

- tablename

- table2name  
+field1 : string  
+field2

Table = Struct.new(:name, :fields)  
Field = Struct.new(:name, :type)

def extract\_db\_spec(file)  
tables = []  
doc = open(file, File::RDONLY) {|f|f.read}  
table\_name = /- (\w\*)\s\*?\n/  
field\_name = /(\s++ (\w+)\s\*(:\s\*(\w\*))?\n)/  
doc.scan /#{table\_name}(#{field\_name}+)/ do |tablename, fields|  
t = Table.new tablename, []  
fields.scan field\_name do |junk, fieldname, junk2, type|  
if type.nil? || type == “”  
if /\w+\_id/ === fieldname  
type = “int”  
else  
type = “string”  
end  
end

```
    t.fields << Field.new(fieldname, type)

  end
  tables << t
end
tables

```

end

einarmagnus

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 8:50am UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/6 "2008-11-19T08:50:42Z")

</div>

On 19.11.2008 07:08, Einar Magnús Boson wrote:

> That is pretty much how, except globals are hardly thread safe I  
> think.

$1 and the like are

robert@fussel ~  
$ ruby -e ‘2.times{|i|Thread.new(i){|ii|4.times{/(\d+)/=~ii.to\_s;puts  
$1;sleep 1}}};sleep 5’  
0  
1  
1  
0  
1  
0  
1  
0

robert@fussel ~  
$

> Use scan instead of gsub:

Right, as far as I can see no replacements should be done. Just read  
only access.

html\_source.scan %r{

(.\*?)

}i do  
table\_souce = $1  
index\_number = table\_source[%r{Index\s+(\d+)}, 1].to\_i

table\_source.scan %r{

(.\*?)}i do  
do\_something\_with $1, index\_number  
end  
end

But a proper HTML parser is probably much better. 🙂

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![knohr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/ecd19e/32.png) [@knohr](https://www.ruby-forum.com/u/knohr)\
**Post date:** [November 19, 2008, 1:57pm UTC](https://www.ruby-forum.com/t/ruby-global-regex-question/153582/7 "2008-11-19T13:57:39Z")

</div>

I use this as an equivalent to global match:

class Regexp  
def global\_match(str, &proc)  
retval = nil  
loop do  
res = str.sub(self) do |m|  
proc.call($~) # pass MatchData obj  
‘’  
end  
break retval if res == str  
str = res  
retval ||= true  
end  
end  
end

re = /…/  
re.global\_match(…) do |m|  
…  
end
