1

Im looking for a PCRE-regex to match lines with "1" before the first-occurrence of "xyz", so with lines like...
Anytext1 Anytext2 xyz Anytext1 xyz AnyText1 xyz
Anytext0 Anytext2 xyz AnyText1 xyz Anytext1 xyz AnyText1 xyz AnyText1 xyz

Only Line1 should be matched, is this possible?

EDIT:
If look-behinds supported variable-quantifiers, I'd just use ^(.*?xyz)(?<=.*1.*xyz).*
That could match the first xyz, then lookbehind for '1' somewhere.

String-lengths vary and '1' can be anywhere, so I cant use multiple lookbehinds with single-quantifiers.
Like if my strings were always 17-chars before xyz, I'd still need 17 different look-behinds like...
^(?:.*?xyz)(?<=.{7}1.{10}xyz).* (matching '1' as the 8th-char, like on Line1)
^(?:.*?xyz)(?<=.{8}1.{11}xyz).* (matching '1' as the 9th-char)
Lol, except 15 more to match all 17 positions, and my strings arent always 17-chars long anyway.

SOLUTION:
Luckily, @The Fourth Bird and @vszholobov instead offered solutions to use a negative lookahead.
Use (.)* with a negative lookahead just before . to test that if . matches, its not 'x' followed by 'yz'.
So the solution I ended up using, looks something like...
^((?!xyz).)*1.*xyz.*

It only matches when '1' appears before the very first 'xyz' in any string.
Just insert ?: into the first group if you dont want any group consumption.. Thanks again everyone!!

  • `/^((?!xyz)[^1])*((?<!xyz)1)/gm` try this. – K450 Jul 24 '21 at 06:07
  • Do not cross matching xyz or 1, then match `1` and match xyz `^(?:(?!xyz|1).)*1.*xyz.*` https://regex101.com/r/Qzf5fw/1 – The fourth bird Jul 24 '21 at 09:54
  • @K450 **Thanks** but no luck. If _only_ look-behinds had variable quantifiers, I'd use ^(.*?xyz)(?<=.*1.*xyz).* Wish I could use multiple look-behinds with single-quantifiers, like ^(.*?xyz)(?<=.{7}1.{10}xyz).* for Line1. Unfortunately, my strings not only vary in length, but that darned "1" could be anywhere within the string. Right now I just cant think of another way around this. At first I thought I was just having a brain fart, but maybe its not so easy after all? – evangeline531 Jul 24 '21 at 10:41
  • 1
    @The fourth bird **Thanks** for this! I was so focused on using look-behinds, I didnt even consider a look-ahead with an alternate. Thanks again. – evangeline531 Jul 24 '21 at 11:03
  • @evangeline531 Can you update your question with what you have tried that you have stated in the comments? – The fourth bird Jul 24 '21 at 13:10
  • @evangeline531 I have added it as an answer. – The fourth bird Jul 25 '21 at 07:51
  • 1
    @The fourth bird and vszholobov.. I tried to upvote your answers, but it keeps saying that I need to have "at least 15 reputation to cast a vote"! I think the upvotes will eventually appear, because it also says... "but your feedback has been recorded". Anyways, I just wanted to thank both of you again! – evangeline531 Jul 26 '21 at 13:35
  • @evangeline531 That is ok, glad it worked for you :-) – The fourth bird Jul 26 '21 at 17:12

2 Answers2

1

You need to match line if its part before 1 first occurrence doesn't contain xyz. It is doable with negative look-arounds.

Example.

More information about matching line which does not contain a word here.

vszholobov
  • 2,133
  • 1
  • 8
  • 23
1

You could use use a negative lookahead to match a single character when either a 1 or xyz is not directly to the right.

Then you can match the 1 and match xyz in the string.

^(?:(?!xyz|1).)*1.*xyz.*
  • ^ Start of string
  • (?: Non capture group to match as a whole part
    • (?!xyz|1). Negative lookahead, assert not xyz or 1 directly to the right
  • )* Close non capture group and optionally repeat it
  • 1.*xyz.* Match 1 and then xyz in the string

Regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70