Regex match negative optional group - regex

I'm trying to match MenuSearch and User in this ocurrencies:
/MenuSearch?action=read
/User
The following regex match the first case:
/\/(.*)(?=\?)/g
But doesn't match User because they doesn't have ? character in your line. How can I can make the second regex group optional?
See online:
https://regex101.com/r/qU6hN6/2

/\/([^?^\n]*)(\?.*)?/g
This grabs a forward slash, \/ , followed by any number of non-? non-newline characters, ([^?^\n]*), optionally followed by a question mark followed by any number of characters, (\?.*)?
The first capture group is the menu item, the second capture group is the query.

You can use this negation based regex:
/^\/([^?]+)/gm
Updated RegEx Demo

You could also use the \w metacharacter if you just need to find word characters.
\/(\w+)/g

Related

Match a part of a string using regex

I have a string and would like to match a part of it.
The string is Accept: multipart/mixedPrivacy: nonePAI: <sip:4168755400#1.1.1.238>From: <sip:4168755400#1.1.1.238>;tag=5430960946837208_c1b08.2.3.1602135087396.0_1237422_3895152To: <sip:4168755400#1.1.1.238>
I want to match PAI: <sip:4168755400#
the whitespace can be a word so i would like to use .* but if i used that it matches most of the string
The example on that link is showing what i'm matching if i use the whitespace instead of .*
(PAI: <sip:)((?:\([2-9]\d{2}\)\ ?|[2-9]\d{2}(?:\-?|\ ?))[2-9]\d{2}[- ]?\d{4})#
The example on that link is showing what i'm trying to achieve with .* but it should only match PAI: <sip:4168755400#
(PAI:.*<sip:)((?:\([2-9]\d{2}\)\ ?|[2-9]\d{2}(?:\-?|\ ?))[2-9]\d{2}[- ]?\d{4})#
I tried lookaround but failing.
Any idea?
thanks
Matching the single space can be updated by using a character class matching either a space or a word character and repeat that 1 or more times to match at least a single occurrence.
Note that you don't have to escape the spaces, and in both occasions you can use an optional character class matching either a space or hyphen [ -]?
If you want the match only, you can omit the 2 capturing groups if you want to.
(PAI:[ \w]+<sip:)((?:\([2-9]\d{2}\) ?|[2-9]\d{2}[ -]?)[2-9]\d{2}[- ]?\d{4})#
Regex demo
The regex should be like
PAI:.*?(<sip:.*?#)
Explanation:
PAI:.*? find the word PAI: and after the word it can be anything (.*) but ? is used to indicate that it should match as few as possible before it found the next expression.
(<sip:.*?#) capturing group that we want the result.
<sip:.*?# find <sip: and after the word it can be anything .*? before it found #.
Example

How to create proper regular expression to find last character which I want to?

I need to create regex to find last underscore in string like 012344_2.0224.71_3 or 012354_5.00123.AR_3.335_8
I have wanted find last part with expression [^.]+$ and then find underscore at found element but I can not handle it.
I hope you can help me :)
Just use a negative character class [^_] that will match everything except an underscore (this helps to ensure no other underscores are found afterwards) and end of string $
Pattern would look as such:
(_)[^_]*$
The final underscore _ is in a capturing group, so you are wanting to return the submatch. You would replace the group 1 (your underscore).
See it live: Regex101
Notice the green highlighted portion on Regex101, this is your submatch and is what would be replaced.
The simplest solution I can imagine is using .*\K_, however not all regex flavours support \K.
If not, another idea would be to use _(?=[^_]*$)
You have a demo of the first and second option.
Explanation:
.*\K_: Fetches any character until an underscore. Since the * quantifier is greedy, It will match until the last underscore. Then \K discards the previous match and then we match the underscore.
_(?=[^_]*$): Fetch an underscore preceeded by non-underscore characters until the end of the line
If you want nothing but the "net" (i.e., nothing matched except the last underscore), use positive lookahead to check that no more underscores are in the string:
/_(?=[^_]*$)/gm
Demo
The pattern [^.]+$ matches not a dot 1+ times and then asserts the end of the string. The will give you the matches 71_3 and 335_8
What you want to match is an underscore when there are no more underscores following.
One way to do that is using a negative lookahead (?!.*_) if that is supported which asserts what is at the right does not match any character followed by an underscore
_(?!.*_)
Pattern demo

Regex excluding catches that ending with a dot

First of all, I don't need full e-mail address validation, my given task doesn't require it. I just want to upgrade my current regex code so that it won't match addresses ending with a dot.
My current code: [0-9A-Za-z.]+[#][0-9A-Za-z.]+
It catches both "user#exampe.com", "user#example.com."
I'd like it to catch only from the string that ends without the dot. user#exampe.com
Example string:
dasd.fas#fsaf.dfas.dsa, zghs#gas.gsq, adg32.dsa12#cas, ksak#c.csa., gs32.basaa#scaa.upc.
I'd like to catch the strings marked as code in the example.
Edit: I have only one line with multiple e-mail addresses separated with a , and a space after them.
You might add [0-9A-Za-z]after your regex to end with what you want to match in your character class without the dot followed by a positive lookahead (?=, |$) that asserts what follows is either a comma followed by a whitespace or the end of the string.
[0-9A-Za-z.]+#[0-9A-Za-z.]+[0-9A-Za-z](?=, |$)
Regex Demo
([0-9A-z.]+#(?:\.?[0-9A-z]+)+)(?=,|$)
Try it here
Just slightly modify your pattern: [0-9A-Za-z.]+[#](?:[a-zA-Z]|\.(?=[a-zA-Z]))+.
It uses alternation after # to match one or more: letters OR dot, if it's followed by another letter, thanks to positive lookahead: \.(?=[a-zA-Z]).
Demo
Try this one:
just capture , , $ and group them in non-capturing group except end .
[0-9A-Za-z.]+[#][0-9A-Za-z.]+[0-9A-Za-z](?:(,|$))
demo here

How can I match all instances of the first letter?

For example, for this string I want to match all A and a:
"All the apples make good cake."
Here's what I did: /(.)[^.]*\1*/ig
I started by getting the first character in the group, which can be any character: (.) Then I added [^.]* because I don't want to match any other character that isn't the first one. Finally I added \1* because I wanted to match the first character again. All other similar variations that I've tried don't seem to work.
The regex you are trying to build would capture very first character then any thing up to the same character as much as possible, using a negative lookahead (tempered dot):
(?i)(\w)(?:(?!\1).)*
Capturing group 1 holds the character you need. Try it on a live demo.
If regex engine supports \K match re-setter token then you can append it to the regex above to only match desired part:
(?i)(\w)(?:(?!\1).)*\K

perl style regex to match nth item in a list

Trying to match the third item in this list:
/text word1, word2, some_other_word, word_4
I tried using this perl style regex to no avail:
([^, ]*, ){$m}([^, ]*),
I want to match ONLY the third word, nothing before or after, and no commas or whitespace. I need it to be a regex, this is not in a program but UltraEdit for a word file.
What can I use to match some_other_word (Or anything third in the list.)
Based on some input by the community members I made the following change to make the logic of the regex pattern clearer.
/^(?:(?:.(?<!,))+,){2}\s*(\w+).*/x
Explanation
/^ # 1.- Match start of line.
(?:(?:.(?<!,))+ # 2.- Match but don't capture a secuence of character not containing a comma ...
,) # 3.- followed by a comma
{2} # 4.- (exactly two times)
\s* # 5.- Match any optional space
(\w+) # 6.- Match and capture a secuence of the characters represented by \w a leat one character long.
.* # 7.- Match anything after that if neccesary.
/x
This is the one suggested previously.
/(?:\w+,?\s*){3}(\w+)/
Try group 1 of this regex:
^(?:.*?,){2}\s*(.*?)\s*(,|$)
See a live demo using your sample, plus an edge case, input showing capture in group 1.
It can't only return one match at a time because your string has more than one occurrence of the same pattern and Regular Expression doesn't have a selective return option! So you can do whatever you want from the returned array.
,\s?([^,]+)
See it in action, 2nd matched group is what you need.