Regexp: named captures

Discussion in 'Ruby' started by Ari Brown, Aug 20, 2007.

  1. Ari Brown

    Ari Brown Guest

    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
    Ari Brown, Aug 20, 2007
    #1
    1. Advertising

  2. Ari Brown

    Sam Smoot Guest

    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. :)
    Sam Smoot, Aug 20, 2007
    #2
    1. Advertising

  3. David A. Black, Aug 20, 2007
    #3
  4. 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
    Marcin Mielżyński, Aug 20, 2007
    #4
  5. On Aug 20, 2:44 pm, Ari Brown <> wrote:
    > 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"
    William James, Aug 20, 2007
    #5
  6. Ari Brown

    Phrogz Guest

    On Aug 20, 3:32 pm, William James <> wrote:
    > On Aug 20, 2:44 pm, Ari Brown <> wrote:
    > > 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
    Phrogz, Aug 20, 2007
    #6
  7. Ari Brown

    Ari Brown Guest

    On Aug 20, 2007, at 4:13 PM, David A. Black wrote:
    > On Tue, 21 Aug 2007, Sam Smoot wrote:
    >
    >> Ruby doesn't have named-captures.

    >
    > 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.
    Ari Brown, Aug 20, 2007
    #7
  8. Ari Brown

    Phrogz Guest

    On Aug 20, 4:00 pm, Ari Brown <> wrote:
    > 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?
    Phrogz, Aug 20, 2007
    #8
  9. Ari Brown

    Ari Brown Guest

    On Aug 20, 2007, at 6:10 PM, Phrogz wrote:

    > 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
    Ari Brown, Aug 21, 2007
    #9
  10. On Aug 20, 4:40 pm, Phrogz <> wrote:
    > On Aug 20, 3:32 pm, William James <> wrote:
    >
    > > On Aug 20, 2:44 pm, Ari Brown <> wrote:
    > > > 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
    William James, Aug 21, 2007
    #10
  11. Hi --

    On Tue, 21 Aug 2007, William James wrote:

    > On Aug 20, 4:40 pm, Phrogz <> wrote:
    >> On Aug 20, 3:32 pm, William James <> wrote:
    >>
    >>> On Aug 20, 2:44 pm, Ari Brown <> wrote:
    >>>> 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)
    David A. Black, Aug 21, 2007
    #11
  12. Ari Brown

    Phrogz Guest

    On Aug 20, 5:17 pm, Ari Brown <> wrote:
    > On Aug 20, 2007, at 6:10 PM, Phrogz wrote:
    >
    > > 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.


    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.
    Phrogz, Aug 21, 2007
    #12
  13. Pretty Printing

    # 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
    Peter Versteegen, Aug 22, 2007
    #13
  14. Ari Brown

    Jimmy Kofler Guest

    Re: Pretty Printing

    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.
    --
    Posted via http://www.ruby-forum.com/.
    Jimmy Kofler, Aug 22, 2007
    #14
  15. Re: Pretty Printing

    Hi Peter.

    On 22 Aug 2007, at 12:21, Peter Versteegen wrote:
    > # 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

    http://douglasfshearer.com
    Douglas F Shearer, Aug 22, 2007
    #15
  16. Ari Brown

    Phlip Guest

    Re: Pretty Printing

    Peter Versteegen wrote:

    > # 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.

    --
    Phlip
    http://www.oreilly.com/catalog/9780596510657/
    ^ assert_xpath
    http://tinyurl.com/yrc77g <-- assert_latest Model
    Phlip, Aug 22, 2007
    #16
  17. Ari Brown

    Ari Brown Guest

    Re: Pretty Printing

    Ruby Reports. Ruport. Check it out.

    On Aug 22, 2007, at 7:21 AM, Peter Versteegen wrote:

    > # 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
    >
    >
    >
    >
    >


    ---------------------------------------------------------------|
    ~Ari
    "I don't suffer from insanity. I enjoy every minute of it" --1337est
    man alive
    Ari Brown, Aug 22, 2007
    #17
  18. Re: Pretty Printing

    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


    On Aug 22, 2007, at 8:07 AM, Douglas F Shearer wrote:

    > Hi Peter.
    >
    > On 22 Aug 2007, at 12:21, Peter Versteegen wrote:
    >> # 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
    >
    > http://douglasfshearer.com
    >
    >
    >
    Peter Versteegen, Aug 23, 2007
    #18
  19. Re: Pretty Printing

    Philip,

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

    Peter


    On Aug 22, 2007, at 10:20 AM, Phlip wrote:

    > Peter Versteegen wrote:
    >
    >> # 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.
    >
    > --
    > Phlip
    > http://www.oreilly.com/catalog/9780596510657/
    > ^ assert_xpath
    > http://tinyurl.com/yrc77g <-- assert_latest Model
    >
    >
    Peter Versteegen, Aug 23, 2007
    #19
  20. Re: Pretty Printing

    Ari,

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

    Thanks,


    Peter


    On Aug 22, 2007, at 3:10 PM, Ari Brown wrote:

    > Ruby Reports. Ruport. Check it out.
    >
    > On Aug 22, 2007, at 7:21 AM, Peter Versteegen wrote:
    >
    >> # 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
    >>
    >>
    >>
    >>
    >>

    >
    > ---------------------------------------------------------------|
    > ~Ari
    > "I don't suffer from insanity. I enjoy every minute of it"
    > --1337est man alive
    >
    >
    >
    >
    >
    Peter Versteegen, Aug 23, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joshua Beall

    Screen captures

    Joshua Beall, Jan 19, 2004, in forum: HTML
    Replies:
    4
    Views:
    439
    Toby A Inkster
    Jan 19, 2004
  2. El Gato

    Regexp captures

    El Gato, Jan 30, 2007, in forum: Ruby
    Replies:
    2
    Views:
    84
    El Gato
    Jan 31, 2007
  3. Joao Silva
    Replies:
    16
    Views:
    340
    7stud --
    Aug 21, 2009
  4. Sarah Allen
    Replies:
    7
    Views:
    155
    Roger Pack
    Mar 2, 2010
  5. Markus Fischer
    Replies:
    9
    Views:
    160
    7stud --
    Apr 8, 2011
Loading...

Share This Page