2

I'm struggling to create some kind of RegEx that can either look ahead or look behind.

Something ideal would be to match the a in both ab and ba, triggered by the presence of the b.

Obviously I could repeat the a, such as:

((?<=b)a)|a(?=b) 

But can it be done without the repetition of the matching set?

anubhava
  • 761,203
  • 64
  • 569
  • 643
Ryan Ward Valverde
  • 6,458
  • 6
  • 37
  • 48

2 Answers2

2

Disclaimer: This answer is using the PCRE syntax/flavor. The syntax may differ from other flavors and some of them don't support it at all.

First of all, I will just warn you that you should just go with the following: (?<=b)a|a(?=b). It's simple and easy to follow.

Now if you want to see another solution, I've come up with the following a(?(?=b)|(?<=b.)). So what does this mean ?

a               # match a
(?              # if
    (?=b)       # there is a "b" ahead
    |           # else
    (?<=b.)     # there is a "b" 2 steps behind
)               # end if

Online demo

HamZa
  • 14,671
  • 11
  • 54
  • 75
  • Just a heads up. The OP has clarified that `a` and `b` are stand-ins for longer strings. However, modifying your expression accordingly would result in a variable-length lookbehind, I believe. – Andrew Cheong Oct 30 '13 at 19:31
  • http://regex101.com/r/eP2bJ8 to match `all` before or after a b. It matches `allb`, `ball` but not `call`. This is really nice. – Ryan Ward Valverde Oct 30 '13 at 19:36
  • @acheong87 Well when I answered it, it wasn't clarified like that. I thought the OP wanted to know a different approach. I struggled a bit and this is the only pattern I could come up with. That's why I said in the beginning of the answer that it's way more easier and cleaner to use `(?<=b)a|a(?=b)`. As for the variable-length lookbehind, there is a not-well-known alternative: the `\K` escape sequence. It will "forget" everything that's matched before (except for the matching groups >= 1). See for example [the following demo](http://regex101.com/r/kZ3hX9). Of course, we can't use it here. – HamZa Oct 30 '13 at 19:45
  • 1
    I know, and I know you answer a lot of the regex questions, so when OP clarified, I wasn't sure you'd get alerted, so I was just giving you a heads up. I was going to edit the `.` in your answer to reflect the clarification for you, but that's where I wasn't sure about variable-length lookbehinds, so I decided not to edit your answer and let you work it out. But in any case, it looks like OP is okay with a set length, _i.e._ `.{3}` as per his example, so everything's fine. I knew vaguely about `\K` but thought that was only supported in a limited set of languages like Perl, PHP, and .NET. – Andrew Cheong Oct 30 '13 at 19:52
  • 1
    Regardless, I wouldn't have thought to use `\K` to get around that problem, so that's nice; thanks. – Andrew Cheong Oct 30 '13 at 19:53
  • @HamZa I like the `\K`, but for some reason my dnGREP doesn't seem to support it. =/ – Ryan Ward Valverde Oct 30 '13 at 20:54
  • @HamZa Do you know if it's possible to construct said regex without having to duplicate the `b`? – Ryan Ward Valverde Nov 05 '13 at 15:14
  • @CayetanoGonçalves is replacing `b` with `\1` for example ok ? What's your goal in the end ? – HamZa Nov 05 '13 at 16:20
1

The matching set seems the simplest and clearest approach to me. That said, you could always build a lookahead-only regex and then apply it to both the target string and its reverse.

Dan Bron
  • 2,313
  • 1
  • 22
  • 35