# Ruby regex lookarounds?

**URL:** <https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771>\
**Category:** Ruby\
**Created:** [March 14, 2007, 8:54am UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771 "2007-03-14T08:54:21Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 14, 2007, 8:54am UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/1 "2007-03-14T08:54:21Z")

</div>

## In Programming Ruby(1st Ed), it says:

The match operators return the character position at which the match  
occurred. They also have the side effect of setting a whole load of Ruby  
variables. $& receives the part of the string that was matched by the  
pattern, $` receives the part of the string that preceded the match, and  
$’ receives the string after the match…

## The match also sets the thread-global variables $~ and $1 through $9. The variable $~ is a MatchData object (described beginning on page 336) that holds everything you might want to know about the match. $1 and so on hold the values of parts of the match.

Here is an example:

irb(main):009:0\> “abc” =~ /(a)(b)/  
=\> 0  
irb(main):010:0\> $&  
=\> “ab”  
irb(main):011:0\> $1  
=\> “a”  
irb(main):012:0\> $2  
=\> “b”

Now and example with a lookbehind:

irb(main):013:0\> “abc” =~ /(?:ab)©/  
=\> 0  
irb(main):014:0\> $&  
=\> “abc”  
irb(main):015:0\> $1  
=\> “c”

Isn’t that output inconsistent? If Ruby wants to say that the regex  
matches the whole string, then shouldn’t $1 be ‘ab’. I know that  
lookarounds shouldn’t be considered part of the match–they are just  
assertions, but Ruby’s $& variable doesn’t seem to respect that.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 14, 2007, 9:35am UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/2 "2007-03-14T09:35:43Z")

</div>

> Isn’t that output inconsistent? If Ruby wants to say that the regex  
> matches the whole string, then shouldn’t $1 be ‘ab’. I know that  
> lookarounds shouldn’t be considered part of the match–they are just  
> assertions, but Ruby’s $& variable doesn’t seem to respect that.

I see what’s going on. (?:ab) is not a grouping: (?: and ) do not form a  
grouping that gets a $ variable. If I write it as (?:(ab)), then ab is  
a grouping:

irb(main):021:0\> “abc” =~ /(?:(ab))©/  
=\> 0  
irb(main):022:0\> $&  
=\> “abc”  
irb(main):023:0\> $1  
=\> “ab”  
irb(main):024:0\> $2  
=\> “c”  
irb(main):025:0\>

It still seems a little strange that $& contains the lookaround.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 14, 2007, 1:30pm UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/3 "2007-03-14T13:30:43Z")

</div>

Hi,

The syntax (?:re) isn’t a lookbehind. It is a grouping form like (re)  
but without capture. So (?:(re)) is the same as (re). Off course, you  
could write something like (?:a(bc)), and you will get “bc” in $1, and  
not “abc”.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 14, 2007, 1:53pm UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/4 "2007-03-14T13:53:46Z")

</div>

On Mar 14, 2007, at 7:30 AM, come wrote:

> The syntax (?:re) isn’t a lookbehind.

Exactly. And just to make this description complete, Ruby 1.8 does  
not support lookbehind.

James Edward G. II

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 18, 2007, 11:42am UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/5 "2007-03-18T11:42:27Z")

</div>

come wrote:

> Hi,
> 
> The syntax (?:re) isn’t a lookbehind. It is a grouping form like (re)  
> but without capture.

I don’t understand the distinction.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 19, 2007, 3:15pm UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/6 "2007-03-19T15:15:15Z")

</div>

Non-capturing grouping is exactly what it sounds like, a group that  
doesn’t  
capture whatever it matches, but still consumes. So…

#non capturing group  
irb(main):009:0\> “1234” =~ /(?:1234)/  
=\> 0  
irb(main):010:0\> $1  
=\> nil

#capturing group  
irb(main):011:0\> “1234” =~ /(1234)/  
=\> 0  
irb(main):012:0\> $1  
=\> “1234”

Lookahead and lookbehind peek ahead or behind without consuming what  
they  
match.

MBL

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [March 18, 2007, 12:31pm UTC](https://www.ruby-forum.com/t/ruby-regex-lookarounds/88771/7 "2007-03-18T12:31:04Z")

</div>

On 18.03.2007 11:42, 7stud 7stud wrote:

> come wrote:
> 
> > The syntax (?:re) isn’t a lookbehind. It is a grouping form like (re)  
> > but without capture.
> 
> I don’t understand the distinction.

Lookahead and -behind do not consume characters while non capturing  
groups do.

robert
