RegEx Substring Extraction - regex

I am trying to write a RegEx on the following text:
CpuUtilization\[GqIF:CA-TORONTO-1-AD-1 | FAULT-DOMAIN-3 | ocid1.image.oc1.ca-toronto-1.aaaaaaaaq4cxrudcxy5seck2cweks2zglo2tfieag6svtvqssa2zmjha | Default | ca-toronto-1 | oke-ccf3jglvbia-nc7pit2gv2a-sa65utwc32a-2 | ocid1.instance.oc1.ca-toronto-1.an2g6ljrwe6j4fqcgrlo7dmzkrtbcgr3jy35gie3qh3w65ctfh3hsd6da | VM.Standard.E2.2\]
I need to extract oke-ccf3jglvbia-nc7pit2gv2a-sa65utwc32a-2 from the statement. The text above can change depending, so looking for a generic RegEx.
I tried using: (\[^\\|\]+)\\|.+ which extract the first occurrence before |

Why use RegEx?
const s = 'CpuUtilization\[GqIF:CA-TORONTO-1-AD-1 | FAULT-DOMAIN-3 | ocid1.image.oc1.ca-toronto-1.aaaaaaaaq4cxrudcxy5seck2cweks2zglo2tfieag6svtvqssa2zmjha | Default | ca-toronto-1 | oke-ccf3jglvbia-nc7pit2gv2a-sa65utwc32a-2 | ocid1.instance.oc1.ca-toronto-1.an2g6ljrwe6j4fqcgrlo7dmzkrtbcgr3jy35gie3qh3w65ctfh3hsd6da | VM.Standard.E2.2\]'
console.log(s.split(" | ")[5])

A regex solution can be
^(?:[^|]+ \| ){5}([^ ]+).*$
^ start of the string
(?:[^|]+ \| ){5} any character but \ followed by |, 5 times. (The ?: makes this a non capturing group).
([^ ]+) your string as the first group
.*$ any character to end of line
To get your string out of this, subtitute it with $1 or \1.
Test it on regex101. There you can test different programming languages/regex processors.
Remark:
Like the answer of Kazi this works in this case, maybe not in others.
There are no more examples in you question.
This answer is in function nearly the same.

Related

Regex to exclude a substring

I am trying to match a param string but exclude any matches when a substring is present.
From my limited regex knowledge this should work to exlude any string containing "porcupine", but it's not. What am I doing wrong?
(\/animal\?.*(?!porcupine).*color=white)
Expected Outcome
| string | matches? |
| ----------------------------------------------- | -------- |
| /animal?nose=wrinkly&type=porcupine&color=white | false |
| /animal?nose=wrinkly&type=puppy&color=white | true |
Actual Outcome
| string | matches? |
| ----------------------------------------------- | -------- |
| /animal?nose=wrinkly&type=porcupine&color=white | true |
| /animal?nose=wrinkly&type=puppy&color=white | true |
Use a Tempered Greedy Token:
/animal\?(?:(?!porcupine).)*color=white
Demo & explanation
The .* searches anything for any number of times, greedily. So you could replace it with a literal search:
(\/animal\?nose=wrinkly\&type=(?!porcupine).*color=white)
See example here: https://regex101.com/r/HJiM2N/1
This may seem overly verbose but it is actually relatively efficient in the number of steps:
(?!\/animal.*?porcupine.*?color)\/animal\?.*color=white
See Regex Demo
If the input string consists of only one and only one occurrence of what you are trying to match and nothing else, then just use the following to ensure that porcupine does not occur anywhere in the input string:
(?!.*porcupine)\/animal\?.*color=white
The code:
import re
tests = [
'/animal?nose=wrinkly&type=porcupine&color=white',
'/animal?nose=wrinkly&type=puppy&color=white'
]
rex = r'(?!\/animal.*?porcupine.*?color)\/animal\?.*color=white'
for test in tests:
m = re.search(rex, test)
print(test, 'True' if m else 'False')
Prints:
/animal?nose=wrinkly&type=porcupine&color=white False
/animal?nose=wrinkly&type=puppy&color=white True

Unable to format RegEx to handle Dollar Sign ($)

I am stuck trying to figure out how to get a RegEx text search to work with a dollar sign. Let's say I have two strings:
TestPerson One | 123456789 | ($100.00) | $0 | 03/27/2018 | Open
TestPerson Two | 987654321 | ($250.00) | ($25) | 03/27/2018 | Open
Using jQuery, I am creating the RegEx. If I was to search for TestPerson, the RegEx would look like this:
/^(?=.*\bTestPerson).*$/i
This would return both strings, as they both contain TestPerson. If I try and search for $, I get zero results even though both strings contian a $. I know the dollar sign is a special character in RegEx, but escaping it does not work either.
How can I format my RegEx to where searching for $ will return both results?
Thanks!
I think this seems multiline modifier on-off problem. I guess you turned off the multiline modifier and implemented the regex so the unexpected output results. Demo
If you turned on the multiline modifier, you could get the output you want. Demo
To check whether or not a string contains a substring, you don't regex: JavaScript has the string method includes(). This method searches a string for a given value and returns true if it exists in the string and false otherwise.
var a = [
'TestPerson One | 123456789 | ($100.00) | $0 | 03/27/2018 | Open',
'TestPerson Two | 987654321 | ($250.00) | ($25) | 03/27/2018 | Open'
]
a.forEach(function(s) {
console.log(s.includes('TestPerson') && s.includes('$'))
})

lookahead in the middle of regex doesn't match

I have a string $s1 = "a_b"; and I want to match this string but only capture the letters. I tried to use a lookahead:
if($s1 =~ /([a-z])(?=_)([a-z])/){print "Captured: $1, $2\n";}
but this does not seem to match my string. I have solved the original problem by using a (?:_)instead, but I am curious to why my original attempt did not work? To my understanding a lookahead matches but do not capture, so what did I do wrong?
A lookahead looks for next immediate positions and if a true-assertion takes place it backtracks to previous match - right after a - to continue matching. Your regex would work only if you bring a _ next to the positive lookahead ([a-z])(?=_)_([a-z])
You even don't need (non-)capturing groups in substitution:
if ($s1 =~ /([a-z])_([a-z])/) { print "Captured: $1, $2\n"; }
Edit
In reply to #Borodin's comment
I think that moving backwards is the same as a backtrack which is more recognizable by debugging the whole thing (Perl debug mode):
Matching REx "a(?=_)_b" against "a_b"
.
.
.
0 <> <a_b> | 0| 1:EXACT <a>(3)
1 <a> <_b> | 0| 3:IFMATCH[0](9)
1 <a> <_b> | 1| 5:EXACT <_>(7)
2 <a_> <b> | 1| 7:SUCCEED(0)
| 1| subpattern success...
1 <a> <_b> | 0| 9:EXACT <_b>(11)
3 <a_b> <> | 0| 11:END(0)
Match successful!
As above debug output shows at forth line of results (when 3rd step took place) engine consumes characters a_ (while being in a lookahead assertion) and then we see a backtrack happens after successful assertion of positive lookahead, engine skips whole sub-pattern in a reverse manner and starts at the position right after a.
At line #5, engine has consumed one character only: a. Regex101 debugger:
How I interpret this backtrack is more clear in this illustration (Thanks to #JDB, I borrowed his style of representation)
a(?=_)_b
*
|\
| \
| : a (match)
| * (?=_)
| |↖
| | ↖
| |↘ ↖
| | ↘ ↖
| | ↘ ↖
| | : _ (match)
| | ^ SUBPATTERN SUCCESS (OP_ASSERT :=> MATCH_MATCH)
| * _b
| |\
| | \
| | : _ (match)
| | : b (match)
| | /
| |/
| /
|/
MATCHED
By this I mean if lookahead assertion succeeds - since extraction of parts of input string is happened - it goes back upward (back to previous match offset - (eptr (pointer into the subject) is not changed but offset is) and while resetting consumed chars it tries to continue matching from there and I call it a backtrack. Below is a visual representation of steps taken by engine with use of Regexp::Debugger
So I see it a backtrack or a kind of, however if I'm wrong with all these said, then I'd appreciate any reclaims with open arms.

Regular expression to finding position of a delimiter and remove all except third delimiter notepad++

text example:
ABC | 123 | target | abc.txt |
CDEFG | 12345 | target | [df:ejk] |
need to remove all except the "target"
Below is what the result should look like.
target
target
How can I achieve this?
thanks for help..
I can suggest this regex for Find what field:
(?:[^\n|]*?\|){2}\s*([^\n|]*?)\s*\|[^\n|]*?\|
Replace with $1.
You can replace this
[a-zA-Z]*\s\|\s[0-9]*\s\|\s([a-zA-Z]*)\s\|\s[a-zA-Z\:\.\[\]]*\s\|
by this
\1
To remove all exept third column.

Regex - Contains pattern but not starting with xyz

I'm trying to match a number pattern in a text file.
The file can contain values such as
12345 567890
90123 string word word 54616
98765
The pattern should match on any line that contains a 5 digit number that does not start with 1234
I have tried using ((?!1234).*)[[:digit:]]{5} but it does not give the desired results.
Edit: The pattern can occur anywhere in the line and should still match
Any suggestions?
This regex should work for matching a line containing a number at least 5 digits long iff the line does not start with '12345':
^((?!12345).*\d{5}.*)$
Short explanation:
^((?!12345).*\d{5}.*)$ _____________
^ \_______/\/\___/\/ ^__|match the end|
_____________________________| | _| | |__ |of the line |
|match the start of a line| | | __|____ |
______________________________|_ | |match ey| |
|look ahead and make sure the | | |exactly | |
|line does not begin with "12345"| | |5 digits| |
___|_____ |
|match any|______|
|character|
|sequence |
EDIT:
It seems that the question has been edited, so this solution no longer reflects the OP's requirements. Still I'll leave it here in case someone looking for something similar lands on this page.
The following would work, using \b to match word boundaries such as start of string or space:
\b(?!12345)\d{5}.*
try this, contains at least 5 decimal digits but not 12345 using a negative look behind
\d{5,}(?<!12345)