Regexp: named captures

A

Ari Brown

How do named captures in Ruby work? This is what I've tried:

irb(main):001:0> if /(?<name>.+)/ =~ /ari/
irb(main):002:1> puts $name
irb(main):003:1> end
SyntaxError: compile error
(irb):1: undefined (?...) sequence: /(?<name>.+)/
from (irb):3

and if I do this:

irb(main):007:0> if /(<name>.+)/ =~ /ari/
irb(main):008:1> puts $name
irb(main):009:1> end
TypeError: can't convert Regexp into String
from (irb):7

I get a Regexp => String error.

Bwah?
aRi
-------------------------------------------|
Nietzsche is my copilot
 
S

Sam Smoot

Ruby doesn't have named-captures.

Coming from .NET myself, at first I was dissapointed. Eventually I
grew to love the simplicity of $1, $2, etc, but that's just me. :)
 
M

Marcin Mielżyński

Ari Brown pisze:
How do named captures in Ruby work? This is what I've tried:

irb(main):001:0> if /(?<name>.+)/ =~ /ari/
irb(main):002:1> puts $name
irb(main):003:1> end

1.9 supports that (so will 2.0):

if match = /(?<name>blah)/.match("blah")
puts match["name"]
end


lopex
 
W

William James

How do named captures in Ruby work? This is what I've tried:

irb(main):001:0> if /(?<name>.+)/ =~ /ari/
irb(main):002:1> puts $name
irb(main):003:1> end
SyntaxError: compile error
(irb):1: undefined (?...) sequence: /(?<name>.+)/
from (irb):3

and if I do this:

irb(main):007:0> if /(<name>.+)/ =~ /ari/
irb(main):008:1> puts $name
irb(main):009:1> end
TypeError: can't convert Regexp into String
from (irb):7

I get a Regexp => String error.

Bwah?
aRi
-------------------------------------------|
Nietzsche is my copilot

A work-around:

md = "foo bar".match( /(\w+) (\w+)/ )
==>#<MatchData:0x2851ef0>
name, surname = md.captures
==>["foo", "bar"]
name
==>"foo"
surname
==>"bar"
 
P

Phrogz

A work-around:

md = "foo bar".match( /(\w+) (\w+)/ )
==>#<MatchData:0x2851ef0>
name, surname = md.captures
==>["foo", "bar"]
name
==>"foo"
surname
==>"bar"

Or my favorite (courtesy of Ara):

_, name, surname = /(\w+) (\w+)/.match("foo bar").to_a
 
A

Ari Brown

The new regex engine, Oniguruma, does. You can install it in 1.8, and
it's included in 1.9/2.0.

I've read about Oniguruma - is it just a different engine behind
class Regex, and it won't change the syntax, right?

Because there's a Regexp wrapper I'm writing (with much help from
Robert Klemme) that uses Regex as the base, and all of the current
syntax.

~ Ari
English is like a pseudo-random number generator - there are a
bajillion rules to it, but nobody cares.
 
P

Phrogz

I've read about Oniguruma - is it just a different engine behind
class Regex, and it won't change the syntax, right?

Because there's a Regexp wrapper I'm writing (with much help from
Robert Klemme) that uses Regex as the base, and all of the current
syntax.

What do you mean by "change the syntax"?

For example, Oniguruma supports named captures (per this thread) and
zero-width negative lookbehind assertions, and ... more.

Certainly the syntax is different for new features, which cause the
current regexp engine to barf. Do you mean syntax inside the regex? Or
the syntax for declaring a regex? Or are you interested only in
backwards compatibility?
 
A

Ari Brown

What do you mean by "change the syntax"?

I mean change the basic regexp syntax.
For example, Oniguruma supports named captures (per this thread) and
zero-width negative lookbehind assertions, and ... more.

Certainly the syntax is different for new features, which cause the
current regexp engine to barf. Do you mean syntax inside the regex? Or
the syntax for declaring a regex? Or are you interested only in
backwards compatibility?

So yea, just backwards compatibility.

Is Oniguruma behind a new class Oniguruma.new or behind Regexp.new

Sorry, but I can't seem to find much documentation on it.

Ari
-------------------------------------------|
Nietzsche is my copilot
 
W

William James

A work-around:
md = "foo bar".match( /(\w+) (\w+)/ )
==>#<MatchData:0x2851ef0>
name, surname = md.captures
==>["foo", "bar"]
name
==>"foo"
surname
==>"bar"

Or my favorite (courtesy of Ara):

_, name, surname = /(\w+) (\w+)/.match("foo bar").to_a

name, surname = /(\w+) (\w+)/.match("foo bar").captures
 
D

David A. Black

Hi --

How do named captures in Ruby work? This is what I've tried:
A work-around:
md = "foo bar".match( /(\w+) (\w+)/ )
==>#<MatchData:0x2851ef0>
name, surname = md.captures
==>["foo", "bar"]
name
==>"foo"
surname
==>"bar"

Or my favorite (courtesy of Ara):

_, name, surname = /(\w+) (\w+)/.match("foo bar").to_a

name, surname = /(\w+) (\w+)/.match("foo bar").captures

That has the disadvantage that it will blow up if the match fails (no
captures method for nil).


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
P

Phrogz

I mean change the basic regexp syntax.



So yea, just backwards compatibility.

Is Oniguruma behind a new class Oniguruma.new or behind Regexp.new

Sorry, but I can't seem to find much documentation on it.

I believe that under 1.8 it comes as its own class, but in 1.9 on it
is the code behind the builtin Regexp class. (I could be wrong,
though. There may be a way to build 1.8 using Oniguruma as the basis
for Regexp.)

And, from what I know, all regex features available in 1.8 use the
same syntax in Oniguruma.
 
P

Peter Versteegen

# Hi,

# I need some help in simplefying my life
# I need to create lots of tables from arrays and I need to provide
# each of the columns with a heading. For eample, I have
# two headings "a-value" and "b-value" specified as follows:
a = ["a-value", "b-value"]
b = [10, 10]
# The array b contains the width of the field, so that I get:
# a-value b-value
# Two ways to do this are as follows:
puts "#{'a-value'.rjust(10)}#{'b-value'.rjust(10)}"
puts "#{a[0].rjust(b[0])}#{a[1].rjust(b[1])}"

# which is difficult to debug, so that I'm looking for
# a simpler process, specificaly by writing a function.
# The following one works:

def heading2(x, n)
x.length.times do |i|
print "#{x.rjust(n)}"
end
print "\n\n"
end

puts
heading2(a,b)

# But this approach doesn't. Why not? Are there other ways to make
this simpler?

def heading1(x, n)
s = ""
x.length.times do |i|
s = s + "\#{\'" + x + "\'.rjust(" + n.to_s + ")}"
end
p s
print s
puts s
return s
end

heading1(a,b)
puts "#{heading1(a, b)}"
puts "\"#{heading1(a, b)}\""


# Thanks ahead. (NOTE: This file can be run from TextMate)



Peter Versteegen
(e-mail address removed)
 
J

Jimmy Kofler

How about using "rescue nil" ?

ruby -e 'name, surname = /(\w+) (\w+)/.match("foo bar").captures rescue
nil; p name, surname'
=> "foo"
=> "bar"

ruby -e 'name, surname = /(\w+) (\w+)/.match("").captures rescue nil; p
name, surname'
=> nil
=> nil


Cheers,

j.k.
 
D

Douglas F Shearer

Hi Peter.

# But this approach doesn't. Why not? Are there other ways to make
this simpler?

Maybe I've got the wrong end of the stick on this, but I get it to
work like this:

==========================

a = ["a-value","b-value", "c-value"]
b = [10,30,15]

def header(names, widths)
header = ''
names.each_with_index do |v,i|
header += v.rjust widths
end
header
end

p header(a, b)

==========================

Hope this helps.

Douglas F Shearer
(e-mail address removed)
http://douglasfshearer.com
 
P

Phlip

Peter said:
# But this approach doesn't. Why not? Are there other ways to make
this simpler?

Here's an idea that's simpler ... if you already have all the tools in place.

Push your raw data into XML. Write an XSLT that converts it to XHTML.
Pipe this thru `lynx -dump`.

No joke: I have done that to produce beautiful automated text-only
e-mails, containing tables of data.
 
A

Ari Brown

Ruby Reports. Ruport. Check it out.

# Hi,

# I need some help in simplefying my life
# I need to create lots of tables from arrays and I need to provide
# each of the columns with a heading. For eample, I have
# two headings "a-value" and "b-value" specified as follows:
a = ["a-value", "b-value"]
b = [10, 10]
# The array b contains the width of the field, so that I get:
# a-value b-value
# Two ways to do this are as follows:
puts "#{'a-value'.rjust(10)}#{'b-value'.rjust(10)}"
puts "#{a[0].rjust(b[0])}#{a[1].rjust(b[1])}"

# which is difficult to debug, so that I'm looking for
# a simpler process, specificaly by writing a function.
# The following one works:

def heading2(x, n)
x.length.times do |i|
print "#{x.rjust(n)}"
end
print "\n\n"
end

puts
heading2(a,b)

# But this approach doesn't. Why not? Are there other ways to make
this simpler?

def heading1(x, n)
s = ""
x.length.times do |i|
s = s + "\#{\'" + x + "\'.rjust(" + n.to_s + ")}"
end
p s
print s
puts s
return s
end

heading1(a,b)
puts "#{heading1(a, b)}"
puts "\"#{heading1(a, b)}\""


# Thanks ahead. (NOTE: This file can be run from TextMate)



Peter Versteegen
(e-mail address removed)


---------------------------------------------------------------|
~Ari
"I don't suffer from insanity. I enjoy every minute of it" --1337est
man alive
 
P

Peter Versteegen

Douglas,

Thanks, this works also. The result is put in a string and the
string is printed.

I guess what I was trying to do is to create a string that ruby is
supposed to interpret, or execute. Perhaps there is another command
to accomplish this.

Peter


Hi Peter.

# But this approach doesn't. Why not? Are there other ways to
make this simpler?

Maybe I've got the wrong end of the stick on this, but I get it to
work like this:

==========================

a = ["a-value","b-value", "c-value"]
b = [10,30,15]

def header(names, widths)
header = ''
names.each_with_index do |v,i|
header += v.rjust widths
end
header
end

p header(a, b)

==========================

Hope this helps.

Douglas F Shearer
(e-mail address removed)
http://douglasfshearer.com
 
P

Peter Versteegen

Philip,

That sounds complicated, given my current state of knowledge of Ruby,
but thanks for the recommendation

Peter
 
P

Peter Versteegen

Ari,

Had not come across Ruport. Sounds interesting, especially since I
have to do a lot of reporting. I will investigate further.

Thanks,


Peter


Ruby Reports. Ruport. Check it out.

# Hi,

# I need some help in simplefying my life
# I need to create lots of tables from arrays and I need to provide
# each of the columns with a heading. For eample, I have
# two headings "a-value" and "b-value" specified as follows:
a = ["a-value", "b-value"]
b = [10, 10]
# The array b contains the width of the field, so that I get:
# a-value b-value
# Two ways to do this are as follows:
puts "#{'a-value'.rjust(10)}#{'b-value'.rjust(10)}"
puts "#{a[0].rjust(b[0])}#{a[1].rjust(b[1])}"

# which is difficult to debug, so that I'm looking for
# a simpler process, specificaly by writing a function.
# The following one works:

def heading2(x, n)
x.length.times do |i|
print "#{x.rjust(n)}"
end
print "\n\n"
end

puts
heading2(a,b)

# But this approach doesn't. Why not? Are there other ways to
make this simpler?

def heading1(x, n)
s = ""
x.length.times do |i|
s = s + "\#{\'" + x + "\'.rjust(" + n.to_s + ")}"
end
p s
print s
puts s
return s
end

heading1(a,b)
puts "#{heading1(a, b)}"
puts "\"#{heading1(a, b)}\""


# Thanks ahead. (NOTE: This file can be run from TextMate)



Peter Versteegen
(e-mail address removed)


---------------------------------------------------------------|
~Ari
"I don't suffer from insanity. I enjoy every minute of it"
--1337est man alive
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top