3

I am looking for a way to match an optional ABC in the following strings. Both strings should be matched either way, if ABC is there or not:

precedingstringwithundefinedlenghtABCsubsequentstringwithundefinedlength precedingstringwithundefinedlenghtsubsequentstringwithundefinedlength

I've tried

.*(ABC).*

which doesn't work for an optional ABC but making ABC non greedy doesn't work either as the .* will take all the pride:

.*(ABC)?.*

This is NOT a duplicate to e.g. Regex Match all characters between two strings as I am looking for a certain string inbetween two random string, kind of the other way around.

dmuensterer
  • 1,875
  • 11
  • 26
  • 2
    so it should match if `ABC` is there or if it is not there? that means it should always match ?!? – user16320675 Sep 15 '22 at 09:10
  • @user16320675 Well in my case I have to use Regex. Otherwise there are obviously better methods. – dmuensterer Sep 15 '22 at 09:33
  • @user16320675 exactly, it should always match, but I want the ABC grouped if it’s there. – dmuensterer Sep 15 '22 at 09:34
  • @user16320675 Yes it is. I didn’t ask for a Java way to do it but for a regular expression. I have included example code that makes it clear that I want to group the match. Read again. – dmuensterer Sep 15 '22 at 09:35
  • I have included two regex examples. And I have intentionally included the Java tag because my regex runs on a Java machine. I am not able to change the code. I didn’t ask for a way to use a Java function, did I? – dmuensterer Sep 15 '22 at 09:52

4 Answers4

1

You can use

.*(ABC).*|.*

This works like this:

  • .*(ABC).* pattern is searched for first, since it is the leftmost part of an alternation (see "Remember That The Regex Engine Is Eager"), it looks for any zero or more chars other than line break chars as many as possible, then captures ABC into Group 1 and then matches the rest of the line with the right-hand .*
  • | - or
  • .* - is searched for if the first alternation part does not match.

Another solution without the need to use alternation:

^(?:.*(ABC))?.*

See this regex demo. Details:

  • ^ - start of string
  • (?:.*(ABC))? - an optional non-capturing group that matches zero or more chars other than line break chars as many as possible and then captures into Group 1 an ABC char sequence
  • .* - zero or more chars other than line break chars as many as possible.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

I’ve come up with an answer myself: Using the OR operator seems to work:

(?:(?:.*(ABC))|.*).*

If there’s a better way, feel free to answer and I will accept it.

dmuensterer
  • 1,875
  • 11
  • 26
-4

You could use this regex: .*(ABC){0,1}.*. It means any, optional{min,max}, any. It is easier to read. I can' t say if your solution or mine is faster due to the processing speed. Options: {value} = n-times {min,} = min to infinity {min,max} = min to max

  • 1
    There is no difference between `{0,1}` and `?`, so it doesn’t solve the OP’s problem at all. – Holger Sep 15 '22 at 09:17
  • If you write `{min,}` the range is min- infinity – Kruger_Doggie Sep 15 '22 at 09:18
  • `.*(ABC){0,1}.*` is not helpful, it is the same as `.*` and matches any string. It is because the first `.*` grabs the whole string and then `(ABC){0,1}` matches an empty string at the end of string, and the match is returned. – Wiktor Stribiżew Sep 15 '22 at 09:25
-4

.+([ABC])?.+ should do the job

noah
  • 312
  • 2
  • 13
  • 2
    try it first.... – user16320675 Sep 15 '22 at 09:27
  • `.*([ABC])?.*` is not helpful, it is the same as `.*` and matches any string. It is because the first `.*` grabs the whole string and then `([ABC])?` matches an empty string at the end of string, and the match is returned. – Wiktor Stribiżew Sep 15 '22 at 09:29
  • https://regex101.com/r/zxtdoM/1 – noah Sep 15 '22 at 09:30
  • @noah Right, you can see `ABC` is not captured, not highlighted, at https://regex101.com/r/zxtdoM/1. – Wiktor Stribiżew Sep 15 '22 at 09:32
  • @wiktor afaik it's in capture group 1, should be able to access that – noah Sep 15 '22 at 09:34
  • Yes, but Group 1 value is an empty string here. That is the problem and I explained why it is like this in my comment above. – Wiktor Stribiżew Sep 15 '22 at 09:38
  • 2
    @WiktorStribiżew even worse, `[ABC]` can never match `ABC` *in general*. – Holger Sep 15 '22 at 09:41
  • @Holger In light of how the regex works, it is not even important what is inside Group 1 since the regex engine never consumes the text Group 1 pattern is supposed to match. – Wiktor Stribiżew Sep 15 '22 at 09:50
  • 1
    @WiktorStribiżew it’s indeed not important to the result (though it highlights even more that this answer could have suggested to just use `.*` to the same result). But it’s important in that this answerer changed `ABC` to `[ABC]` a) for no reason and b) apparently without understanding the meaning of the regex constructs. – Holger Sep 15 '22 at 09:54