3

I'm using google re2 regex for the purpose of querying Prometheus on Grafana dashboard. Trying to get value from key by below 3 types of possible input strings

 1. object{one="ab-vwxc",two="value1",key="abcd-eest-ed-xyz-bnn",four="obsoleteValues"}
 2. object{one="ab-vwxc",two="value1",key="abcd-eest-xyz-bnn",four="obsoleteValues"}
 3. object{one="ab-vwxc",two="value1",key="abcd-eest-xyz-bnn-ed",four="obsoleteValues"}

..with validation as listed below

  • should contain abcd-
  • shouldn't contain -ed

Somehow this regex

\bkey="(abcd(?:-\w+)*[^-][^e][^d]\w)"

..satisfies the first condition abcd- but couldn't satisfy the second condition (negating -ed).

The expected output would be abcd-eest-xyz-bnn from the 2nd input option. Any help would be really appreciated. Thanks a lot.

CdVr
  • 323
  • 3
  • 15

2 Answers2

5

If I understand your requirements correctly, the following pattern should work:

\bkey="(abcd(?:-e|-(?:[^e\W]|e[^d\W])\w*)*)"

Demo.

Breakdown for the important part:

(?:                 # Start a non-capturing group.
    -e              # Match '-e' literally.
    |               # Or the following...
    -               # Match '-' literally.
    (?:             # Start a second non-capturing group.
        [^e\W]      # Match any word character except 'e'.
        |           # Or...
        e[^d\W]     # Match 'e' followed by any word character except 'd'.
    )               # Close non-capturing group.
    \w*             # Match zero or more additional word characters.
)                   # Close non-capturing group.

Or in simple terms:

Match a hyphen followed by:

  • only the letter 'e'. Or..
  • a word* not starting with 'e'. Or..
  • a word starting with 'e' not followed by 'd'.

*A "word" here means a string of word characters as defined in regex.

  • I think you can remove the first `-e|` if I am not mistaken. Nice pattern ++ – The fourth bird Jul 23 '20 at 19:59
  • Just trying to understand, what if when i need to negate the letter pattern **-edf** then?. Do i need to do like below? \bkey="(abcd(?:-e|-(?:[^e\W]|e[^d\W]|ed[^f\W])\w*)*)" – CdVr Jul 23 '20 at 20:03
  • 1
    @Thefourthbird Thanks! I'm not sure what the minimum number characters the OP expects after each hyphen is. If it's one, then I believe the `-e|` part is needed, otherwise, it wouldn't accept `e` alone after the hyphen. If the minimum is two, for example, then `-e|` won't be required but we'll need to throw another `\w` after the first character class. – 41686d6564 stands w. Palestine Jul 23 '20 at 20:03
  • @CdVr You're so close. I would just use `-ed?|` instead of `-e|` in that case. See the [demo](https://regex101.com/r/UCiBI7/1). – 41686d6564 stands w. Palestine Jul 23 '20 at 20:12
  • @AhmedAbdelhameed So far good. But the pattern `abcd-` need not be the starting. I've updated question with 4th input option where need to match `ktm-` and `abcd-` and negate `-edf'. I try updating ur regex, but seems i'm doing something wrong. I tried in the following [link](https://regex101.com/r/TxOK08/2). can u pls correct me if i'm wrong? – CdVr Jul 24 '20 at 08:18
  • @CdVr Please don't edit the question and change the requirements after receiving answers. You can always ask a new question, or you can ask for further assistance in the comments if it's something trivial (I've rolled it back; kindly, don't re-edit). That being said, you may simply use the same pattern in my previous comment but replace `abcd` with `(?:abcd|ktm)`. Full pattern: `\bkey="((?:abcd|ktm)(?:-ed?|-(?:[^e\W]|e[^d\W]|ed[^f\W])\w*)*)"`. See the [demo](https://regex101.com/r/PcRDfa/1). – 41686d6564 stands w. Palestine Jul 24 '20 at 08:25
  • @AhmedAbdelhameed sure will adhere your statement. But, `(?:abcd|ktm)` should not be OR rather it should be AND. So, i've to match both `ktm-` and `abcd-` and not `-edf`. I mean two cases would be satisfy for output. 1. match(abcd-) and notMatch(-edf) OR 2. match(ktm-) and match(abcd-) and notMatch(-edf). The result would satisfy the 2nd and 4th input in the question – CdVr Jul 24 '20 at 08:34
  • @CdVr I'm not sure I understand you. Examples you used in the link either have `abcd` _**OR**_ `ktm` (in each line). What am I missing? – 41686d6564 stands w. Palestine Jul 24 '20 at 08:36
  • @CdVr This might be a good time to ask a new question where you can explain more with better examples. You may add a link to this question there to provide context. – 41686d6564 stands w. Palestine Jul 24 '20 at 08:38
  • @CdVr Side note: I noticed that you have asked a few questions so far but you never accepted any of the answers that you received. You might want to go through your questions, review the answers, and accept the ones that helped. See; [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers) Good luck! – 41686d6564 stands w. Palestine Jul 24 '20 at 08:45
  • Just a min. I try a last pick. If the string matches `abcd-`, it should negate `-edf` OR if the string matches `ktm-` it should also matches `abcd-` and then negate `edf`. The output would give two result as follows: `abcd-eest-xyz-bnn` and `ktm-qg-abcd-eest-xyz-bnn`. Is this clear now? I voted ur answer. Thanks for ur time! – CdVr Jul 24 '20 at 08:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/218505/discussion-between-cdvr-and-ahmed-abdelhameed). – CdVr Jul 24 '20 at 08:49
  • Voted up your answer but it seems like OP needs to ensure `abcd` an an element is present *and* there is no element starting with `ed` irrelevant of their respective placing in the key. Am I correct @CdVr? – JvdV Jul 24 '20 at 12:04
  • 1
    That was right only. but i need to cover another scenario. That is as a whole, i need to negate `-ed` in both the cases. In 1st case, string should start with `abcd-` and negate `-ed` 2nd scenario is that when string starts with `ktm-` it should also contain `abcd-` and negate `-ed`. Am i clear now? @JvdV – CdVr Jul 24 '20 at 13:42
1

Maybe have a go with:

\bkey="((?:ktm-(?:(?:e-|[^e]\w*-|e[^d]\w*-)*)abcd(?:(?:-e|-[^e]\w*|-e[^d]\w*)*)|abcd(?:(?:-e|-[^e]\w*|-e[^d]\w*)*)))"

This would ensure that:

  • String starts with either ktm- or abcd.
  • If starts with ktm-, there should at least be an element called abcd.
  • If starts with abcd, there doesn't have to be another element.
  • Both options check that there must not be an element starting with -ed.

See the online demo

The struggle without lookarounds...

JvdV
  • 70,606
  • 8
  • 39
  • 70
  • no dude. But, its taking value along with the key. Need only the value. Moreover, I got that after several attempts. Please check this [link](https://regex101.com/r/I5Wsbf/2). Thanks for ur effort though. Rather for points ur contribution here is immense. Appreciated. I'm attempting another where applying regex on the value which is matching two conditions but not negating (not satisfying the negate). If u want to contribute pls ref this [link](https://regex101.com/r/I5Wsbf/3) thanks! – CdVr Jul 24 '20 at 16:16
  • @CdVr. The only thing missing was the capture group to take the value alone. See the update. – JvdV Jul 24 '20 at 16:25
  • any idea about the second link / the following one? [link](https://regex101.com/r/I5Wsbf/3) negate is not working! – CdVr Jul 24 '20 at 16:27
  • The answer I given does what you want. I don't understand what you are trying to show in the link – JvdV Jul 24 '20 at 16:29
  • i mean [this](https://regex101.com/r/I5Wsbf/4) satisfies the 2 match cases but not satisfying the notMatch case of `-ed` in it. It return true even if that string contains `-ed` in it. Hoping this is clear! – CdVr Jul 25 '20 at 07:52
  • My answer ***does*** negate `-ed` @CdVr. In what way does it not work. – JvdV Jul 25 '20 at 08:05
  • After ur updated answer it served the OP. But, not the first comment (another question) of ur answer. For the OP i've upVoted this! Thanks! – CdVr Jul 25 '20 at 09:49
  • I really don't understand what you mean but I'm glad it worked. – JvdV Jul 25 '20 at 09:57
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/218571/discussion-between-cdvr-and-jvdv). – CdVr Jul 25 '20 at 10:05