Forum: Ruby Regular Expressions

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-01 20:13
Hi everyone.

Just a question about regualar expression in Ruby. Is there a way to
check in each line of a document for always beginning with "23430000"
and somewhere on that same line another string 'CodeRed'?

line1: 23430000 @#$#$3455000CodeRed 24AAWERE 740000000

This is what I have so far when I import each textdata from another
file.


textdata.should =~ /23430000/ |CodeRed/

...the pipe was supposed to determine if CodeRed exists somewhere after
the identity code 23430000. However, it doesn't work like this. Also for
my code I am not using OR logic with it.
B09f4659460545e38ece34ddd0d96b46?d=identicon&s=25 Yaser Sulaiman (Guest)
on 2008-12-01 20:41
(Received via mailing list)
I'm not sure if this is what you are asking for, but /23430000.*CodeRed/
will match a line that contains '23430000', followed by zero or more
characters, and then 'CodeRed'.

try in IRB:

irb(main):001:0> line1 = '23430000 @#$#$3455000CodeRed 24AAWERE
740000000'
=> "23430000 @\#$\#$3455000CodeRed 24AAWERE 740000000"
irb(main):002:0> line1 =~ /23430000.*CodeRed/
=> 0
irb(main):003:0> line2 = '23430000 @#$#$3455000CodeGreen 24AAWERE
740000000'
=> "23430000 @\#$\#$3455000CodeGreen 24AAWERE 740000000"
irb(main):004:0> line2 =~ /23430000.*CodeRed/
=> nil

Regards,
Yaser Sulaiman
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2008-12-01 20:43
(Received via mailing list)
On Dec 1, 2008, at 1:08 PM, Mmcolli00 Mom wrote:

> Hi everyone.

Hello.

> Just a question about regualar expression in Ruby. Is there a way to
> check in each line of a document for always beginning with "23430000"
> and somewhere on that same line another string 'CodeRed'?

Sure.

> line1: 23430000 @#$#$3455000CodeRed 24AAWERE 740000000
>
> This is what I have so far when I import each textdata from another
> file.
>
>
> textdata.should =~ /23430000/ |CodeRed/

   textdata.should =~ /\A23430000.*CodeRed/

My changes are simple:

* \A is a regex atom the only matches at the beginning of the input.
I used this to make sure 23430000 is at the beginning of the line and
not later.
* .* matches zero or more of pretty much anything.  Newlines are the
only character excluded.  Thus this allows anything to appear between
the number and CodeRed.

Now the regex above really just checks one line.  If you want to check
all lines, you'll want something like:

   textdata.each do |line|
     line.should =~ /\A23430000.*CodeRed/
   end

Hope that helps.

James Edward Gray II
9dec3df8319c613f6f4f14a27da0fdb4?d=identicon&s=25 Kyle Schmitt (Guest)
on 2008-12-01 20:56
(Received via mailing list)
On Mon, Dec 1, 2008 at 1:08 PM, Mmcolli00 Mom <mmc_collins@yahoo.com>
wrote:
>
>
> textdata.should =~ /23430000/ |CodeRed/
>
> ...the pipe was supposed to determine if CodeRed exists somewhere after
> the identity code 23430000. However, it doesn't work like this. Also for
> my code I am not using OR logic with it.
> --
> Posted via http://www.ruby-forum.com/.

I just wanted to mention another way of combining regexes that may
help you stay sane: union.

#You write each regex nice and simple like..
startswith=/~23430000/
codered=/CodeRed/

#Then combine them to a complex one
combined_regex=Regexp.union(startswith,codered)

When you've got to build up some large regular expressions, this can
be a godsend, especially when revisiting code you haven't looked at in
awhile.

--Kyle
9dec3df8319c613f6f4f14a27da0fdb4?d=identicon&s=25 Kyle Schmitt (Guest)
on 2008-12-01 20:58
(Received via mailing list)
On Mon, Dec 1, 2008 at 1:51 PM, Kyle Schmitt <kyleaschmitt@gmail.com>
wrote:
> When you've got to build up some large regular expressions, this can
> be a godsend, especially when revisiting code you haven't looked at in
> awhile.
>
> --Kyle

Scratch that, not thinking clearly!  This is to match startswith OR
codered, not necessarily both.

Still, I maintain that this is a way of staying sane with complex
regexes :)
B09f4659460545e38ece34ddd0d96b46?d=identicon&s=25 Yaser Sulaiman (Guest)
on 2008-12-01 21:19
(Received via mailing list)
On Mon, Dec 1, 2008 at 10:52 PM, Kyle Schmitt <kyleaschmitt@gmail.com>
wrote:
>
> Still, I maintain that this is a way of staying sane with complex regexes
:)
>
It certainly looks helpful. I didn't know about it before. Thanks for
sharing :)

Regards,
Yaser
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-01 21:23
Kyle Schmitt wrote:
> On Mon, Dec 1, 2008 at 1:51 PM, Kyle Schmitt <kyleaschmitt@gmail.com>
> wrote:
>> When you've got to build up some large regular expressions, this can
>> be a godsend, especially when revisiting code you haven't looked at in
>> awhile.
>>
>> --Kyle
>
> Scratch that, not thinking clearly!  This is to match startswith OR
> codered, not necessarily both.
>
> Still, I maintain that this is a way of staying sane with complex
> regexes :)

Alright. thanks for the tip. I was just thinking...what is the
regexpression for starts with anyway? I don't know..I figured maybe I
could use union with the starts with expression and then just grab that
value.
Cf63da956b6ba955687a2f2f262928cb?d=identicon&s=25 Mmcolli00 Mom (mmcolli00)
on 2008-12-01 21:24
thanks everyone!
73ba5e17cf39ee5aa4ada6eefdb80177?d=identicon&s=25 Joe Wölfel (Guest)
on 2008-12-01 22:39
(Received via mailing list)
On 1 déc. 08, at 14:52, Kyle Schmitt wrote:

>> combined_regex=Regexp.union(startswith,codered)
>
> Still, I maintain that this is a way of staying sane with complex
> regexes :)
>

Interesting that there is a union function but no intersection function.
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2008-12-01 23:14
(Received via mailing list)
On Dec 1, 2008, at 4:32 PM, Joe Wölfel wrote:
>>> #Then combine them to a complex one
>> codered, not necessarily both.
>>
>> Still, I maintain that this is a way of staying sane with complex
>> regexes :)
>>
>
> Interesting that there is a union function but no intersection
> function.


How would you even define a regexp (re) that matched only when both of
two other regexps (re1, re2) matched?

     class Regexp
       def self.intersection(re1,re2)
         union(compile(/(?>#{re1}).*#{re2}/),
               compile(/(?>#{re2}).*#{re1}/))
       end
     end

     re = Regexp.intersection(re1,re2)

What would you expect the value to be?  And while Regexp.union is well-
behaved for multiple arguments, the expansion for more arguments in
the intersection gets ugly fast.

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2008-12-01 23:14
(Received via mailing list)
Joe Wölfel wrote:
> Interesting that there is a union function but no intersection function [for
regexen].

Well, the union of two regexen /foo/ and /bar/ is simply /foo|bar/, so
the
union method is rather easily implemented. An intersection method would
be
somewhat more complex. Of course that's not really a reason not to
implement
it, but it might be the reason why it's not implemented yet.

HTH,
Sebastian
73ba5e17cf39ee5aa4ada6eefdb80177?d=identicon&s=25 Joe Wölfel (Guest)
on 2008-12-01 23:47
(Received via mailing list)
On 1 déc. 08, at 17:08, Rob Biedenharn wrote:

>>>>
>>>
>
>     re = Regexp.intersection(re1,re2)
>
> What would you expect the value to be?  And while Regexp.union is
> well-behaved for multiple arguments, the expansion for more
> arguments in the intersection gets ugly fast.
>
> -Rob
>
> Rob Biedenharn    http://agileconsultingllc.com
> Rob@AgileConsultingLLC.com

Not sure I understand.  Are you arguing that an intersection cannot
exist as a regular expression or merely that it is hard?
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2008-12-02 00:04
(Received via mailing list)
On Dec 1, 2008, at 5:41 PM, Joe Wölfel wrote:
>>>>> codered=/CodeRed/
>>>>> --Kyle
>>
>>
>
> Not sure I understand.  Are you arguing that an intersection cannot
> exist as a regular expression or merely that it is hard?

That it becomes combinatorially hard to construct such a regexp in
general. If I want a regexp that matches the intersection of /a/ and /
b/ and /c/ (i.e., contains each of 'a', 'b', and 'c'), I have to
account for all the permutations (manually):
/a.*b.*c/
/a.*c.*b/
/b.*a.*c/
/b.*c.*a/
/c.*a.*b/
/c.*b.*a/

Or combined as:  /(?:a.*(?:b.*c)|(?:c.*b))|(?:b.*(?:a.*c)|(?:c.*a))|
(?:c.*(?:b.*a)|(?:a.*b))/

That's nasty and so much worse than the union /[abc]/ or /a|b|c/ even
for this relatively simple case.  It would be better to do this at the
application level if you can't guarantee order:

[/a/, /b/, /c/].all? {|re| mystring =~ re }

And then the value of the match can be whatever the application wants
to track.

-Rob
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 Ken Bloom (Guest)
on 2008-12-02 02:40
(Received via mailing list)
On Mon, 01 Dec 2008 17:08:16 -0500, Rob Biedenharn wrote:

>>>> #Then combine them to a complex one
>>> codered, not necessarily both.
> two other regexps (re1, re2) matched?
> What would you expect the value to be?  And while Regexp.union is well-
> behaved for multiple arguments, the expansion for more arguments in the
> intersection gets ugly fast.

It's very well defined if you're talking about an underlying
deterministic finite automaton. That's an simple proof that is usually
assigned as an exercise for the student in a computer science theory
course.

If re1 compiles to a DFA dfa1=(S1,s1,A1,f1)
where S1 is the set of all states, s1 is the start state, A1 is the set
of accepting states, and f1(s'1,input) is the transition function
and re2 compiles to a DFA dfa2=(S2,s2,A2,f2)

Then the intersection of these two languages can be recognized by the
DFA
dfa3=(S1 x S2, (s1,s2), A1 x A2, f3)
where x means the cartesian product, and
f3((s'1,s'2),input)=(f1(s'1,input),f2(s'2,input))

Now, how you'd turn that back into a regexp is not so easy...
(but still doable)

--Ken
18d3c84ca5a017fe3e96490afaea28aa?d=identicon&s=25 Richard Conroy (Guest)
on 2008-12-04 01:07
(Received via mailing list)
On Mon, Dec 1, 2008 at 7:08 PM, Mmcolli00 Mom <mmc_collins@yahoo.com>
wrote:
>
>
> textdata.should =~ /23430000/ |CodeRed/
>
> ...the pipe was supposed to determine if CodeRed exists somewhere after
> the identity code 23430000. However, it doesn't work like this. Also for
> my code I am not using OR logic with it.

I just simply have to pimp http://www.rubular.com/

I don't think that I have closed that browser tab containing it in
weeks.
Its killer feature is the ability to supply your own test data.
http://www.rubular.com

/^23430000.*CodeRed.*$/
This topic is locked and can not be replied to.