gnychis
gnychis

Reputation: 7555

a regex that matches "something|more|here" but not "something|more|here|"

I am trying to work out a regex that matches the following:

[something|more|here]
[another|match]
[more|matches|of|any|length]

However, I do not want it to match:

[a|bad|example|]
[|another|bad|example]
[a|bad||example|again]

What I currently have is:

/\A:\[[a-zA-Z\|]*\]/

This is not stringent enough since its just looking for any combination of letters and | signs in-between []. It needs to not match || or a leading or trailing |. What might be a good way to match on this?

Upvotes: 0

Views: 63

Answers (5)

Bohemian
Bohemian

Reputation: 425318

No look arounds required:

/\[[a-z]+(\|[a-z]+)*\]/i

See demo

This is variation of a fairly standard approach to matching CSV input; it takes the general form of:

stuff(,stuff)*

Upvotes: 3

daremkd
daremkd

Reputation: 8424

I would add some look-ahead assertions for this:

(?!.*\|\|)(?!.*\|\])(?!.*\[\|)\[[a-zA-Z\|]+\]

Basically, there are 3 combinations you are trying to NOT match:

a) ||

b) [|

c) |]

and these 3 look-ahead assertions take care of that. If you're not familiar with look-ahead assertions, you have some nice tutorials you can read. I didn't get them the first time, so try reading 3-4 articles on the topic and watching some YouTube videos and you'll get it :)

Upvotes: 1

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89629

You can use this pattern:

\[[a-zA-Z]+(?:\|[a-zA-Z]+)*\]

With several regex flavors, escaping the closing square brackets is not needed, so you can write:

\[[a-zA-Z]+(?:\|[a-zA-Z]+)*]

And for a more general case that is not limited to ascii letters you can use:

\[[^\]|]+(?:\|[^\]|]+)*\]

or

\[[^]|]+(?:\|[^]|]+)*]

Upvotes: 0

Aivean
Aivean

Reputation: 10882

As simple, as:

 \[([a-zA-Z]+(\|[a-zA-Z]+)*)\]

You can put ? in the end, if you want to match empty brackets too:

 \[([a-zA-Z]+(\|[a-zA-Z]+)*)?\]

UPD: forgot the brackets, fixed

Upvotes: 1

Sam
Sam

Reputation: 20486

Expression

\[(?!\|)(?:[^|\]]|\|(?!\|))*(?<!\|)\]

Demo


Explanation

  • \[ start with [
  • (?!\|) negative lookahead to make sure [ isn't followed by |
  • (?:[^|\]]|\|(?!\|))* non-capturing group repeated 0+ times:
    • [^|\]] anything but a | or a ]
    • | or
    • \|(?!\|) a | not followed by a second |
  • (?<!\|) negative lookbehind to make sure ] isn't preceded by |
  • \] end with ]

Upvotes: 0

Related Questions