Forum: Ruby Regexp to match strings that _don't_ being with a string

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.
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 20:24
I would like to write a regexp that will match a string that does NOT
start with a specified set of characters.

For example,

Given:

xyz123
asldfhsl
xyk2345

and assume that I want to see only strings that don't start with "xyz"
(so in this case, the last 2 in the list).

I tried /^[^(xyz)]/ but I don't trust it.  I don't think the grouping
will take inside the character class.

Do I need a negative lookahead assertion?

Thanks,
Wes
5c841628b56df3a68984986e9f095d01?d=identicon&s=25 Andrew Johnson (andrew)
on 2006-03-28 20:39
(Received via mailing list)
On Wed, 29 Mar 2006 03:24:36 +0900, Wes Gamble <weyus@att.net> wrote:

> I tried /^[^(xyz)]/ but I don't trust it.  I don't think the grouping
> will take inside the character class.

The [^(xyz)] creates a negative character class, so your regex would
match any string that started with a character not in the given set.
Not what you really want

> Do I need a negative lookahead assertion?

That would be a simple solution: /^(?!xyz)/  which will match when
the beginning of the line/string is not followed by 'xyz'.

andrew
2e34f386b20cb7c11c4204d699babd78?d=identicon&s=25 Chris Alfeld (Guest)
on 2006-03-28 20:40
(Received via mailing list)
What about:

! s =~ /^xyz/

There is a good discussion of doing exactly this with negative
look-aheads in 'man perlre'.  It's... ugly.
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 20:43
In my example, won't /^(?!xyz)/ also match

29384723xyz02342

which is a little more than I want?

WG

Andrew Johnson wrote:
> On Wed, 29 Mar 2006 03:24:36 +0900, Wes Gamble <weyus@att.net> wrote:
>
>> I tried /^[^(xyz)]/ but I don't trust it.  I don't think the grouping
>> will take inside the character class.
>
> The [^(xyz)] creates a negative character class, so your regex would
> match any string that started with a character not in the given set.
> Not what you really want
>
>> Do I need a negative lookahead assertion?
>
> That would be a simple solution: /^(?!xyz)/  which will match when
> the beginning of the line/string is not followed by 'xyz'.
>
> andrew
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-28 20:46
(Received via mailing list)
On Mar 28, 2006, at 12:40 PM, Chris Alfeld wrote:

> ! s =~ /^xyz/

Ruby has a doesn't match operator for this:

   s !~ /^xyz/

James Edward Gray II
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 20:56
Hey that's too easy!!!

Thanks James.

I'm liking Ruby more and more :).

Wes

James Gray wrote:
> On Mar 28, 2006, at 12:40 PM, Chris Alfeld wrote:
>
>> ! s =~ /^xyz/
>
> Ruby has a doesn't match operator for this:
>
>    s !~ /^xyz/
>
> James Edward Gray II
5c841628b56df3a68984986e9f095d01?d=identicon&s=25 Andrew Johnson (andrew)
on 2006-03-28 20:59
(Received via mailing list)
On Wed, 29 Mar 2006 03:43:51 +0900, Wes Gamble <weyus@att.net> wrote:
> In my example, won't /^(?!xyz)/ also match
>
> 29384723xyz02342
>
> which is a little more than I want?

Uhm, maybe I've misunderstood (wouldn't be the first time) -- I thought
you
wanted to match strings that did not begin with 'xyz' ... and as far as
I
can tell, "29384723xyz02342" does not start with 'xyz'.

  while DATA.gets
    print if ~/^(?!xyz)/
  end
  __END__
  xyefoo
  xyzpfoo
  asdfsdf
  1230xyzasdf

produces:

  xyefoo
  asdfsdf
  1230xyzasdf


puzzled,
andrew
F3b7109c91841c7106784d229418f5dd?d=identicon&s=25 Justin Collins (Guest)
on 2006-03-28 21:03
(Received via mailing list)
Wes Gamble wrote:
>> On Mar 28, 2006, at 12:40 PM, Chris Alfeld wrote:
>>
>>
>>> ! s =~ /^xyz/
>>>
>> Ruby has a doesn't match operator for this:
>>
>>    s !~ /^xyz/
>>
>> James Edward Gray II
>>
Awesome.

-Justin
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 21:30
Andrew,

That works fine.

In actuality, I do need the ability to pass one regex to do the job into
another utility that will use it to operate on an array of strings.

So although !~ is cool, I really didn't want to have to iterate through
the strings myself.

Thanks,
Wes

Andrew Johnson wrote:
> On Wed, 29 Mar 2006 03:43:51 +0900, Wes Gamble <weyus@att.net> wrote:
>> In my example, won't /^(?!xyz)/ also match
>>
>> 29384723xyz02342
>>
>> which is a little more than I want?
>
> Uhm, maybe I've misunderstood (wouldn't be the first time) -- I thought
> you
> wanted to match strings that did not begin with 'xyz' ... and as far as
> I
> can tell, "29384723xyz02342" does not start with 'xyz'.
>
>   while DATA.gets
>     print if ~/^(?!xyz)/
>   end
>   __END__
>   xyefoo
>   xyzpfoo
>   asdfsdf
>   1230xyzasdf
>
> produces:
>
>   xyefoo
>   asdfsdf
>   1230xyzasdf
>
>
> puzzled,
> andrew
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 22:01
I have a new wrinkle.

Now I want to match any line that doesn't have "xyz" or "abc" at the
beginning of the line.

Is there a way to "AND" together the input to the negative lookahead
assertion?

Wes

Wes Gamble wrote:
> Andrew,
>
> That works fine.
>
> In actuality, I do need the ability to pass one regex to do the job into
> another utility that will use it to operate on an array of strings.
>
> So although !~ is cool, I really didn't want to have to iterate through
> the strings myself.
>
> Thanks,
> Wes
>
> Andrew Johnson wrote:
>> On Wed, 29 Mar 2006 03:43:51 +0900, Wes Gamble <weyus@att.net> wrote:
>>> In my example, won't /^(?!xyz)/ also match
>>>
>>> 29384723xyz02342
>>>
>>> which is a little more than I want?
>>
>> Uhm, maybe I've misunderstood (wouldn't be the first time) -- I thought
>> you
>> wanted to match strings that did not begin with 'xyz' ... and as far as
>> I
>> can tell, "29384723xyz02342" does not start with 'xyz'.
>>
>>   while DATA.gets
>>     print if ~/^(?!xyz)/
>>   end
>>   __END__
>>   xyefoo
>>   xyzpfoo
>>   asdfsdf
>>   1230xyzasdf
>>
>> produces:
>>
>>   xyefoo
>>   asdfsdf
>>   1230xyzasdf
>>
>>
>> puzzled,
>> andrew
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-28 22:09
(Received via mailing list)
Wes Gamble wrote:
> I have a new wrinkle.
>
> Now I want to match any line that doesn't have "xyz" or "abc" at the
> beginning of the line.
>
> Is there a way to "AND" together the input to the negative lookahead
> assertion?

For lookaheads, you can get AND by concatenating:


irb(main):001:0> /^(?!abc)(?!xyz)/ =~ "abc"
=> nil
irb(main):002:0> /^(?!abc)(?!xyz)/ =~ " abc"
=> 0
irb(main):003:0> /^(?!abc)(?!xyz)/ =~ "xyz"
=> nil
irb(main):004:0> /^(?!abc)(?!xyz)/ =~ " xyz"
=> 0
Bb4bdf2b184027bc38d4fb529770cde5?d=identicon&s=25 Wes Gamble (weyus)
on 2006-03-28 22:16
Thanks, that makes sense since the lookahead doesn't "consume" right?

WG
Joel VanderWerf wrote:
> Wes Gamble wrote:
>> I have a new wrinkle.
>>
>> Now I want to match any line that doesn't have "xyz" or "abc" at the
>> beginning of the line.
>>
>> Is there a way to "AND" together the input to the negative lookahead
>> assertion?
>
> For lookaheads, you can get AND by concatenating:
>
>
> irb(main):001:0> /^(?!abc)(?!xyz)/ =~ "abc"
> => nil
> irb(main):002:0> /^(?!abc)(?!xyz)/ =~ " abc"
> => 0
> irb(main):003:0> /^(?!abc)(?!xyz)/ =~ "xyz"
> => nil
> irb(main):004:0> /^(?!abc)(?!xyz)/ =~ " xyz"
> => 0
7264fb16beeea92b89bb42023738259d?d=identicon&s=25 Christian Neukirchen (Guest)
on 2006-03-28 22:30
(Received via mailing list)
Wes Gamble <weyus@att.net> writes:

> Thanks,
> Wes

I always wanted to propose a ~ operator for Regexps. ;-)
The current behavior is next to useless.

It wouldn't be difficult to add... also, see lib/eregex.rb.
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-28 22:59
(Received via mailing list)
Wes Gamble wrote:
> Thanks, that makes sense since the lookahead doesn't "consume" right?

Right.  In this case an alternation works, too:

p %w{abcd xyz as}.map {|s| /^(?!abc|xyz)/=~s}
=> [nil, nil, 0]

De Morgan's Law comes to mind: not a and not b <=> not(a or b) :-)

Kind regards

	robert
This topic is locked and can not be replied to.