-1

I'm looking to match the following: xxxxxApplexxxxxOrangexxxxx

I need a regex expression which will match this string with either Apple + Orange or Orange + Apple AND will only match if both words are found in the string.

Update: I liked @lagripe's answer (?=.*?(Apple))(?>.*?(Orange) as that one could be used easily within in my program. I'll be generating the regex expression programmatically based on N number of words. Thanks

bobble bubble
  • 16,888
  • 3
  • 27
  • 46
  • 1
    What have you tried? What didn't work? What did you get? What did you expect? What doesn't work with your code and where is it? – Toto Oct 11 '19 at 16:07

3 Answers3

2

.*(apple.*orange|orange.*apple).*

https://rubular.com/r/kwolGiWLBSkPPF

gaga5lala
  • 1,218
  • 13
  • 17
1

You can use this regex :

(?=.*?(Apple))(?>.*?(Orange))

Demo :

Here

Resource to why atomic groups are used for lookaround cases :

lagripe
  • 766
  • 6
  • 18
  • Your regex matches `xxxOrangexxxxxxxOrangexxxxxxxx` ;) – bobble bubble Oct 11 '19 at 16:32
  • 1
    @bobblebubble fixed – lagripe Oct 11 '19 at 16:40
  • 1
    Right, removed my answer as it's almost duplicate now. I'd use the lookahead only at start `^(?=.*?Apple)`. This will improve performance. Else it's used at each position. – bobble bubble Oct 11 '19 at 16:44
  • Your answer has shown to be incorrect so you need to correct it or delete it. – Cary Swoveland Oct 11 '19 at 17:10
  • @CarySwoveland could you elaborate more ? – lagripe Oct 11 '19 at 17:12
  • @bobblebubble's comment shows that your regex does not meet the requirement, "...AND will only match if both words are found in the string". It would work if you had `(?=.*?(Orange))` rather than `(?>.*?(Orange))` (`(?>..` creates an *atomic grouping*). That could well have been an oversight (as it was for me). – Cary Swoveland Oct 11 '19 at 17:19
  • @CarySwoveland correct me if im wrong but the problem was to solve the thing that you are telling me im wrong about ( AND will only match if both words are found in the string.).Concerning bobblebubble's comment, i already fixed the problem. Could you care and see the demo i already attached ? and it would be nice to provide some incorrect strings that won't go along with the pattern. – lagripe Oct 11 '19 at 18:45
  • Why would you use a positive lookahead for `"Apple"` and create an atomic group for `"Orange"`? Any why put `"Apple"` and `"Orange"` in capture groups? If you want to use a positive lookahead for `"Apple"` why not just `/(?=.*?Apple).*Orange/`? – Cary Swoveland Oct 11 '19 at 19:00
  • are you arguing that the pattern is incorrect or something else ? I'm sorry, i'm not following you anymore! For your example it won't work for the way around (Orange then Apple), Also added a resource to the answer – lagripe Oct 11 '19 at 19:13
  • 1
    All I'm saying is that your answer is unnecessarily complex. There's no need for capture groups or the atomic group when you can simplify to `/(?=.*?Apple).*Orange/`. I don't know what you mean by "it won't work the other way around": `'xxOrangexxApplexx'.match? /(?=.*?Apple).*Orange/ #=> true`. I had an answer containing an atomic group by accident (I meant to use a positive lookahead) that worked fine, but that doesn't mean it was a good solution, which is why I deleted it. – Cary Swoveland Oct 11 '19 at 20:58
  • 1
    @CarySwoveland also your idea `/(?=.*?Apple).*Orange` is missing the start anchor which makes it slow. If you don't put the start anchor, the lookahead is triggered at each position. Further I'm with you that there's no need for any capturing or atomic groups :) – bobble bubble Oct 12 '19 at 09:34
1
r = /Apple.*Orange|Orange.*Apple/

'xxApplexxOrangexx'.match?(r)  #=> true
'xxOrangexxApplexx'.match?(r)  #=> true
'xxApplexxApplexx'.match?(r)   #=> false
'xxOrangexxOrangexx'.match?(r) #=> false
'xxApplexx'.match?(r)          #=> false
'xxOrangexx'.match?(r)         #=> false
'xxxx'.match?(r)               #=> false
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100