Regular expressions question

Hey, can we keep this to a discussion of language features and stop insulting large portions of the Ruby community? Thank you.

James Edward Gray II

···

On Dec 15, 2005, at 2:12 PM, Neil Stevens wrote:

Jeff Wood wrote:

I'll shut up now.

I think that's exactly what some people want you to do. People don't
want to be told that they're lousy coders, and their poor practices have
only been made to work through a special case in the language interpreter.

Can we please try to keep it civil in here? You go code how you want and I will go code how I want and we can both be happy.

-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster

509-577-7732
ezra@yakima-herald.com

···

On Dec 15, 2005, at 12:12 PM, Neil Stevens wrote:

Jeff Wood wrote:

I'll shut up now.

I think that's exactly what some people want you to do. People don't
want to be told that they're lousy coders, and their poor practices have
only been made to work through a special case in the language interpreter.

yes, thank you. this is a better description of the problem. i am not a
native english speaker, so may be this is one of the reasons why my
question is not clear.

i saw a solution to this problem that uses split at the end. it of
course won't work if you change your example and allow quoted strings
in source-words and destination-words. a quoted string can contain
anything, spaces too and your keywords too, so the subsequent split
won't work.

well, i did not realise that the term "group's captures" is that rare.
i thought it was a standard term. but may be i am brainwashed by
microsoft. so i have this code in .net which might help to clarify what
i am talking about:

            string text = "One car red car blue car";
            string pat = @"^(?:(\w+)\s+)*(\w+)$";
            Regex r = new Regex(pat, RegexOptions.IgnoreCase);

            // Match the regular expression pattern against a text
string.
            Match m = r.Match(text);
            if (m.Success)
            {
                Console.WriteLine("match: [{0}]", m);
                foreach (Group g in m.Groups)
                {
                    Console.WriteLine("group: [{0}]", g);
                    foreach (Capture c in g.Captures)
                    {
                        Console.WriteLine("\tcapture: [{0}]", c);
                    }
                }
            }

the output is:

match: [One car red car blue car]
group: [One car red car blue car]
        capture: [One car red car blue car]
group: [blue]
        capture: [One]
        capture: [car]
        capture: [red]
        capture: [car]
        capture: [blue]
group: [car]
        capture: [car]

as you see, the first group is $0, the second group is $1, and the
third is $2. but $1 and $2 contain captures too. it is like if $1 and
$2 were arrays in Ruby.

in my opinion this is a big limitation of ruby's regular expressions.
it just must be as powerful as .net ; -)

konstantin

Neil Stevens wrote:

My mistake, heh. I wonder how many who use them know that, though, and
how many just do it without checking because it's popular in perl or
popular on here.

Hold on, this wasn't really my mistake, I think. How is one supposed to
know a dollar-sign variable isn't always global?

This sounds to me like some special-case hackery done to keep careless
coders from shooting themselves in the foot.

···

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin

Neil Stevens <neil@hakubi.us> writes:

James Edward Gray II wrote:

Also, I believe they are thread-local variables are they not? (I'm
honestly asking.) If so, I don't see a lot of concern about them being
stomped on before they are used.

Actually, I just looked it up, and according to "Programming Ruby,"
$1-$9 are "local to the current scope."

My mistake, heh. I wonder how many who use them know that, though, and
how many just do it without checking because it's popular in perl or
popular on here.

Actually, these variables are thread-local in Perl too:

  use strict;
  use threads;
  
  "foo" =~ /(\w+)/;
  print($1, "\n");
  threads->new(sub {
           "bar" =~ /(\w+)/;
           print($1, "\n");
         })->join;
  print($1, "\n");

prints:
  
  foo
  bar
  foo

···

Neil Stevens - neil@hakubi.us

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

James Edward Gray II wrote:

Hey, can we keep this to a discussion of language features and stop
insulting large portions of the Ruby community? Thank you.

You are the one who first suggested that more people are using these
special-case magic variables so wantonly in their code, by bringing up
what you said in the Ruby Quiz.

Yeah, it's clear that regardless of how nice the Ruby language is,
nothing can bring up the quality of the average Internet programmer,
unfortunately. Better tools don't make a better carpenter.

···

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin

Ezra Zygmuntowicz wrote:

Can we please try to keep it civil in here? You go code how you want
and I will go code how I want and we can both be happy.

Actually, no, you're wrong. String's gsub, for one, has been hard-wired
to force you to use magic punctuation in order to access the match data.

This forces *everyone* to depend on the pseudo-global variable hacks
unless they run their Regexp multiple times:

str = 'root:*:0:0:System Administrator:/var/root:/bin/sh'
re = /([^:]+)(:|$)/
str.gsub!(re) do |m|
  matchData = re.match(m)
  'x' * matchData[1].length + matchData[2]
end
puts str
  => 'xxxx:x:x:x:xxxxxxxxxxxxxxxxxxxx:xxxxxxxxx:xxxxxxx'

So the langauge is hard-coded to force everyone to use pseudo-global
magically-scoped variables, that you have to cross your fingers and hope
work the way you need at the moment.

···

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin

yes, thank you. this is a better description of the problem. i am not
a native english speaker, so may be this is one of the reasons why my
question is not clear.

i saw a solution to this problem that uses split at the end. it of
course won't work if you change your example and allow quoted strings
in source-words and destination-words. a quoted string can contain
anything, spaces too and your keywords too, so the subsequent split
won't work.

well, i did not realise that the term "group's captures" is that rare.
i thought it was a standard term. but may be i am brainwashed by
microsoft. so i have this code in .net which might help to clarify
what i am talking about:

           string text = "One car red car blue car";
           string pat = @"^(?:(\w+)\s+)*(\w+)$";
           Regex r = new Regex(pat, RegexOptions.IgnoreCase);

           // Match the regular expression pattern against a text
string.
           Match m = r.Match(text);
           if (m.Success)
           {
               Console.WriteLine("match: [{0}]", m);
               foreach (Group g in m.Groups)
               {
                   Console.WriteLine("group: [{0}]", g);
                   foreach (Capture c in g.Captures)
                   {
                       Console.WriteLine("\tcapture: [{0}]", c);
                   }
               }
           }

the output is:

match: [One car red car blue car]
group: [One car red car blue car]
       capture: [One car red car blue car]
group: [blue]
       capture: [One]
       capture: [car]
       capture: [red]
       capture: [car]
       capture: [blue]
group: [car]
       capture: [car]

as you see, the first group is $0, the second group is $1, and the
third is $2. but $1 and $2 contain captures too. it is like if $1 and
$2 were arrays in Ruby.

in my opinion this is a big limitation of ruby's regular expressions.
it just must be as powerful as .net ; -)

konstantin

I don't know whether your question was answered in the lengthy thread already. In case not: in Ruby to get all matches of a group you need to iterate through the whole string with #scan. There is no such thing as this feature of .net - and frankly I haven't missed it so far. To get at all the words in your example this is sufficient:

s = "One car red car blue car"

=> "One car red car blue car"

s.scan /\w+/

=> ["One", "car", "red", "car", "blue", "car"]

If you actually need group matches, you'll have to do something like this

s.scan(/\w(\w+)/).map{|m| m[0]}

=> ["ne", "ar", "ed", "ar", "lue", "ar"]

alternative

ma=

=>

s.scan(/\w(\w+)/) {|m| ma << m[0]}

=> "One car red car blue car"

ma

=> ["ne", "ar", "ed", "ar", "lue", "ar"]

Of course this is quite a silly example... The main point here is that you must refrain from anchoring the regexp at the beginning if you want to iterate like this.

HTH

    robert

···

ako... <akonsu@gmail.com> wrote:

Neil Stevens wrote:

Neil Stevens wrote:

My mistake, heh. I wonder how many who use them know that, though, and
how many just do it without checking because it's popular in perl or
popular on here.

Hold on, this wasn't really my mistake, I think. How is one supposed to
know a dollar-sign variable isn't always global?

This sounds to me like some special-case hackery done to keep careless
coders from shooting themselves in the foot.

Usually if you think about what the variable represents, it's obvious whether it should be thread-local or global, and ruby does it that way. (Results of something the thread did, like call an external process, or match a regex--those are thread local. Environment that was given when the program started--those are global.) The local/global distinction is not hackery, but the notation (inherited from perl) is not great.

I do kinda wish there was a consistent visual cue of some kind, like $$foo for global and $foo for local, or $foo for global and $_foo for local. It would also be nice to have a faster way to access user-defined thread vars: $_foo versus Thread.current[:foo].

···

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hold on, this wasn't really my mistake, I think. How is one supposed to
know a dollar-sign variable isn't always global?

This sounds to me like some special-case hackery done to keep careless
coders from shooting themselves in the foot.

I think it's more like when the intrepid Ruby nuby first notices
a method not suffixed with ! that modifies the receiver--and posts to the list: This is inconsistent! This can't be right!
This violates POLS! etc.! "All methods that modify the receiver
should end in !, right???"

And Matz points out that the rationale is somewhat different. . . .

Similarly, it doesn't seem reasonable to condemn method-local $1..$n
as special-cace hackery designed to benefit careless coders, so much
as Ruby behaving in the most naturally useful way possbile.

Huzzah! &c. :slight_smile:

Regards,

Bill

···

From: "Neil Stevens" <neil@hakubi.us>

James Edward Gray II wrote:

Hey, can we keep this to a discussion of language features and stop
insulting large portions of the Ruby community? Thank you.

You are the one who first suggested that more people are using these
special-case magic variables so wantonly in their code, by bringing up
what you said in the Ruby Quiz.

Since you are educating me about the joys of MatchData, allow me to educate you on the differences of what we both said. I explained what I have seen and made statements about how common a given practice is. You were, and still are, insulting people you know nothing about.

Yeah, it's clear that regardless of how nice the Ruby language is,
nothing can bring up the quality of the average Internet programmer,
unfortunately. Better tools don't make a better carpenter.

You are rude for absolutely no reason and you have ceased to add anything to this conversation. I'm done trying to reason with you.

James Edward Gray II

···

On Dec 15, 2005, at 3:07 PM, Neil Stevens wrote:

Neil Stevens wrote:

Actually, no, you're wrong.

plonk

Hi --

···

On Fri, 16 Dec 2005, Neil Stevens wrote:

Ezra Zygmuntowicz wrote:

Can we please try to keep it civil in here? You go code how you want
and I will go code how I want and we can both be happy.

Actually, no, you're wrong. String's gsub, for one, has been hard-wired
to force you to use magic punctuation in order to access the match data.

This forces *everyone* to depend on the pseudo-global variable hacks
unless they run their Regexp multiple times:

You can minimize it by using $~.

David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails: Ruby techniques for Rails developers",
coming April 2006 (http://www.manning.com/books/black\)

James Edward Gray II wrote:

You are rude for absolutely no reason and you have ceased to add
anything to this conversation. I'm done trying to reason with you.

It's unfortunate that you think it's rude to point out facts that are
uncomfortable to you. It's unfortunate that you're apparently seeing
personal attacks that don't exist.

···

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin

And what "facts" have you mentioned?

To me, the magic variables fit fine with regex.

I find it really hard to understand why people are complaining about
using a little $1 after some string of absolutely cryptic pattern
matching sequences.

People tend to like Ruby's regex system because it's perl-like, no?

But in the interest of preserving TIMTOWTDI, there is an object
oriented solution which many posters have already mentioned.

James saying that it was common practice, and providing evidence of it
is much more reasonable than you simply insulting people you don't
know.

A quote from Arnold in Kindergarden Cop, "Stop Whining!" applies very well here.
You're free to never use $1 .. $n, so I don't see what the issue is.

···

On 12/15/05, Neil Stevens <neil@hakubi.us> wrote:

It's unfortunate that you think it's rude to point out facts that are
uncomfortable to you. It's unfortunate that you're apparently seeing
personal attacks that don't exist.

kill-filed

-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster

509-577-7732
ezra@yakima-herald.com

···

On Dec 15, 2005, at 1:32 PM, Neil Stevens wrote:

James Edward Gray II wrote:

You are rude for absolutely no reason and you have ceased to add
anything to this conversation. I'm done trying to reason with you.

It's unfortunate that you think it's rude to point out facts that are
uncomfortable to you. It's unfortunate that you're apparently seeing
personal attacks that don't exist.

--

Neil Stevens - neil@hakubi.us

I know I said I'd shut up, and I am, but I did feel that after some of
the messages that have popped since mine, that I should have a final
comment...

I do apologize to you all for causing such grief. I was simply trying
to add my $0.02 as what I thought was best practice ... and made the
assumption that most people were doing things that way ( I don't use
the ${x} vars at all, but I bet you knew that already )...

I'm not saying that people are bad coders for using those, I didn't
think I was being insulting in my OP. I was simply suggesting that I
thought it a better practice to show the most oop way of doing things
in code sent to newer programmers ...

Truly, if anybody took offense, it was unintentional. If you knew me
better, you would understand that I tend to be passionate about things,
especially when it comes to teaching the next gen of programmers and/or
users of Ruby...

So, peace, love, and joyful programming to you all, I will try to be
more cautious with my posts in the future.

j.

I too apologize if I came back at you too harsh. It was unintentional.

Group hug everyone! :wink:

James Edward Gray II

···

On Dec 15, 2005, at 7:47 PM, jeff.darklight@gmail.com wrote:

I do apologize to you all for causing such grief.

You have been fairly civil. What I find most amusing is how Neil
started the flame-fest by agreeing to your self-imposed shutting up,
then ended up having the same opinion as you (that the $1 variables
are bad.) Oh the irony.

Ryan

···

On 12/15/05, jeff.darklight@gmail.com <jeff.darklight@gmail.com> wrote:

I do apologize to you all for causing such grief.

Ryan Leavengood wrote:

···

On 12/15/05, jeff.darklight@gmail.com <jeff.darklight@gmail.com> wrote:

I do apologize to you all for causing such grief.

You have been fairly civil. What I find most amusing is how Neil
started the flame-fest by agreeing to your self-imposed shutting up,
then ended up having the same opinion as you (that the $1 variables
are bad.) Oh the irony.

Actually, I think you should read more carefully what I wrote. The
irony here isn't what you think.

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin