# Concatenating Regex Smartly

**URL:** <https://www.ruby-forum.com/t/concatenating-regex-smartly/165028>\
**Category:** Ruby\
**Created:** [April 8, 2009, 11:46am UTC](https://www.ruby-forum.com/t/concatenating-regex-smartly/165028 "2009-04-08T11:46:06Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sshaikh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b77776/32.png) [@sshaikh](https://www.ruby-forum.com/u/sshaikh)\
**Post date:** [April 8, 2009, 11:46am UTC](https://www.ruby-forum.com/t/concatenating-regex-smartly/165028/1 "2009-04-08T11:46:06Z")

</div>

Is there a way of quickly concatenating two full string patterns in a  
way that takes into account the boundaries? So for example:

\A\d+\Z and \A[a-z]+\Z

would give:

\A\d+[a-z]+\Z

?

Or is this a context sensitive situation where I’d have to parse and  
join it myself? If so, what is the best way to “tokenise” a pattern?

Shak

---

<div class="post-metadata">

**Author:** ![sshaikh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b77776/32.png) [@sshaikh](https://www.ruby-forum.com/u/sshaikh)\
**Post date:** [April 8, 2009, 12:01pm UTC](https://www.ruby-forum.com/t/concatenating-regex-smartly/165028/2 "2009-04-08T12:01:39Z")

</div>

On 08.04.2009 11:47, Shak Shak wrote:

> Is there a way of quickly concatenating two full string patterns in a  
> way that takes into account the boundaries? So for example:
> 
> \A\d+\Z and \A[a-z]+\Z

IIRC the “Z” must be lower case.

> would give:
> 
> \A\d+[a-z]+\Z
> 
> ?
> 
> Or is this a context sensitive situation where I’d have to parse and  
> join it myself? If so, what is the best way to “tokenise” a pattern?

Why do you have to parse them? There is a bit of context missing but  
without further facts I would recommend to keep individual patterns  
without the start and end anchors and only apply those after  
constructing the full regexp that you want to use. My 0.02 EUR…

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![sshaikh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b77776/32.png) [@sshaikh](https://www.ruby-forum.com/u/sshaikh)\
**Post date:** [April 8, 2009, 3:23pm UTC](https://www.ruby-forum.com/t/concatenating-regex-smartly/165028/3 "2009-04-08T15:23:08Z")

</div>

Shak Shak wrote:

> \A\d+\Z and \A[a-z]+\Z

These are two regular expressions both anchored to the start and end of  
the string.

If you want to match one or the other:

re1 = /\A\d+\z/  
re2 = /\A[a-z]+\z/

re3 = /#{re1}|#{re2}/  
=\> /(?-mix:\A\d+\z)|(?-mix:\A[a-z]+\z)/

But to “concatenate” in the sense of making a regexp which matches  
digits followed by letters, you need to remove the anchors.

re1 = /\d+/  
re2 = /[a-z]+/

re3 = /\A#{re1}#{re2}\z/  
=\> /\A(?-mix:\d+)(?-mix:[a-z]+)\z/

Note that #{re1} and #{re2} are each surrounded by a non-capturing group  
(?..) when they are interpolated into re3. So it should also work  
properly for more complex REs, e.g.

re1 = /a|b/  
re2 = /c|d/  
re3 = /\A#{re1}#{re2}\z/

But if you want to be extra-certain that it’s done correctly, you can  
always add your own additional layer of grouping:

re3 = /\A(?:#{re1}#{re2})\z/

---

<div class="post-metadata">

**Author:** ![sshaikh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b77776/32.png) [@sshaikh](https://www.ruby-forum.com/u/sshaikh)\
**Post date:** [April 8, 2009, 3:30pm UTC](https://www.ruby-forum.com/t/concatenating-regex-smartly/165028/4 "2009-04-08T15:30:29Z")

</div>

On Wed, Apr 8, 2009 at 12:00 PM, Robert K.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On 08.04.2009 11:47, Shak Shak wrote:
> 
> > Is there a way of quickly concatenating two full string patterns in a  
> > way that takes into account the boundaries? So for example:
> > 
> > \A\d+\Z and \A[a-z]+\Z  
> > Not that I am aware of, their semantics however is slightly different:

irb(main):001:0\> “abc\n” =~ /.\Z/ # \Z matches the \n  
=\> 2  
irb(main):002:0\> “abc\n” =~ /.\z/ # \z does not match the \n and neither  
does .  
=\> nil  
irb(main):003:0\> “abc\n” =~ /.\z/m # Now, in multiline mode, the .  
matches the \n  
=\> 3

Now this is for 1.9 maybe this does not hold for 1.8.  
Cheers  
R.
