Matching newline and any character with Python regex - python

I have a text like
var12.1
a
a
dsa
88
123!!!
secondVar12.1
The string between var and secondVar may be different (and there may be different count of them).
How can I dump it with regexp?
I'm trying something something like this to no avail:
re.findall(r"^var[0-9]+\.[0-9]+[\n.]+^secondVar[0-9]+\.[0-9]+", str, re.MULTILINE)

You can grab it with:
var\d+(?:(?!var\d).)*?secondVar
See demo. re.S (or re.DOTALL) modifier must be used with this regex so that . could match a newline. The text between the delimiters will be in Group 1.
NOTE: The closest match will be matched due to (?:(?!var\d).)*? tempered greedy token (i.e. if you have another var + a digit after var + 1+ digits then the match will be between the second var and secondVar.
NOTE2: You might want to use \b word boundaries to match the words beginning with them: \bvar(?:(?!var\d).)*?\bsecondVar.
REGEX EXPLANATION
var - match the starting delimiter
\d+ - 1+ digits
(?:(?!var\d).)*? - a tempered greedy token that matches any char, 0 or more (but as few as possible) repetitions, that does not start a char sequence var and a digit
secondVar - match secondVar literally.
IDEONE DEMO
import re
p = re.compile(r'var\d+(?:(?!var\d).)*?secondVar', re.DOTALL)
test_str = "var12.1\na\na\ndsa\n\n88\n123!!!\nsecondVar12.1\nvar12.1\na\na\ndsa\n\n88\n123!!!\nsecondVar12.1"
print(p.findall(test_str))
Result for the input string (I doubled it for demo purposes):
['12.1\na\na\ndsa\n\n88\n123!!!\n', '12.1\na\na\ndsa\n\n88\n123!!!\n']

You're looking for the re.DOTALL flag, with a regex like this: var(.*?)secondVar. This regex would capture everything between var and secondVar.

Related

How to create regex to match a string that contains only hexadecimal numbers and arrows?

I am using a string that uses the following characters:
0-9
a-f
A-F
-
>
The mixture of the greater than and hyphen must be:
->
-->
Here is the regex that I have so far:
[0-9a-fA-F\-\>]+
I tried these others using exclusion with ^ but they didn't work:
[^g-zG-Z][0-9a-fA-F\-\>]+
^g-zG-Z[0-9a-fA-F\-\>]+
[0-9a-fA-F\-\>]^g-zG-Z+
[0-9a-fA-F\-\>]+^g-zG-Z
[0-9a-fA-F\-\>]+[^g-zG-Z]
Here are some samples:
"0912adbd->12d1829-->218990d"
"ab2c8d-->82a921->193acd7"
Firstly, you don't need to escape - and >
Here's the regex that worked for me:
^([0-9a-fA-F]*(->)*(-->)*)*$
Here's an alternative regex:
^([0-9a-fA-F]*(-+>)*)*$
What does the regex do?
^ matches the beginning of the string and $ matches the ending.
* matches 0 or more instances of the preceding token
Created a big () capturing group to match any token.
[0-9a-fA-F] matches any character that is in the range.
(->) and (-->) match only those given instances.
Putting it into a code:
import re
regex = "^([0-9a-fA-F]*(->)*(-->)*)*$"
re.match(re.compile(regex),"0912adbd->12d1829-->218990d")
re.match(re.compile(regex),"ab2c8d-->82a921->193acd7")
re.match(re.compile(regex),"this-failed->so-->bad")
You can also convert it into a boolean:
print(bool(re.match(re.compile(regex),"0912adbd->12d1829-->218990d")))
print(bool(re.match(re.compile(regex),"ab2c8d-->82a921->193acd7")))
print(bool(re.match(re.compile(regex),"this-failed->so-->bad")))
Output:
True
True
False
I recommend using regexr.com to check your regex.
If there must be an arrow present, and not at the start or end of the string using a case insensitive pattern:
^[a-f\d]+(?:-{1,2}>[a-f\d]+)+$
Explanation
^ Start of string
[a-f\d]+ Match 1+ chars a-f or digits
(?: Non capture group to repeat as a whole
-{1,2}>[a-f\d]+ Match - or -- and > followed by 1+ chars a-f or digits
)+ Close the non capture group and repeat 1+ times
$ End of string
See a regex demo and a Python demo.
import re
pattern = r"^[a-f\d]+(?:-{1,2}>[a-f\d]+)+$"
s = ("0912adbd->12d1829-->218990d\n"
"ab2c8d-->82a921->193acd7\n"
"test")
print(re.findall(pattern, s, re.I | re.M))
Output
[
'0912adbd->12d1829-->218990d',
'ab2c8d-->82a921->193acd7'
]
You can construct the regex by steps. If I understand your requirements, you want a sequence of hexadecimal numbers (like a01d or 11efeb23, separated by arrows with one or two hyphens (-> or -->).
The hex part's regex is [0-9a-fA-F]+ (assuming it cannot be empty).
The arrow's regex can be -{1,2}> or (->|-->).
The arrow is only needed before each hex number but the first, so you'll build the final regex in two parts: the first number, then the repetition of arrow and number.
So the general structure will be:
NUMBER(ARROW NUMBER)*
Which gives the following regex:
[0-9a-fA-F]+(-{1,2}>[0-9a-fA-F]+)*

How to use "?" in regular expression to change a qualifier to be non-greedy and find a string in the middle of the data? [duplicate]

I have a text like this;
[Some Text][1][Some Text][2][Some Text][3][Some Text][4]
I want to match [Some Text][2] with this regex;
/\[.*?\]\[2\]/
But it returns [Some Text][1][Some Text][2]
How can i match only [Some Text][2]?
Note : There can be any character in Some Text including [ and ] And the numbers in square brackets can be any number not only 1 and 2. The Some Text that i want to match can be at the beginning of the line and there can be multiple Some Texts
JSFiddle
The \[.*?\]\[2\] pattern works like this:
\[ - finds the leftmost [ (as the regex engine processes the string input from left to right)
.*? - matches any 0+ chars other than line break chars, as few as possible, but as many as needed for a successful match, as there are subsequent patterns, see below
\]\[2\] - ][2] substring.
So, the .*? gets expanded upon each failure until it finds the leftmost ][2]. Note the lazy quantifiers do not guarantee the "shortest" matches.
Solution
Instead of a .*? (or .*) use negated character classes that match any char but the boundary char.
\[[^\]\[]*\]\[2\]
See this regex demo.
Here, .*? is replaced with [^\]\[]* - 0 or more chars other than ] and [.
Other examples:
Strings between angle brackets: <[^<>]*> matches <...> with no < and > inside
Strings between parentheses: \([^()]*\) matches (...) with no ( and ) inside
Strings between double quotation marks: "[^"]*" matches "..." with no " inside
Strings between curly braces: \{[^{}]*} matches "..." with no " inside
In other situations, when the starting pattern is a multichar string or complex pattern, use a tempered greedy token, (?:(?!start).)*?. To match abc 1 def in abc 0 abc 1 def, use abc(?:(?!abc).)*?def.
You could try the below regex,
(?!^)(\[[A-Z].*?\]\[\d+\])
DEMO

need regex expression to avoid " \n " character

I want to apply regex to the below string in python Where i only want to capture Model Number : 123. I tried the below regex but it didn't fetch me the result.
string = """Model Number : 123
Serial Number : 456"""
model_number = re.findall(r'(?s)Model Number:.*?\n',string)
Output is as follows Model Number : 123\n How can i avoid \n at the end of the output?
Remove the DOTALL (?s) inline modifier to avoid matching a newline char with ., add \s* after Number and use .* instead of .*?\n:
r'Model Number\s*:.*'
See the regex demo
Here, Model Number will match a literal substring, \s* will match 0+ whitespaces, : will match a colon and .* will match 0 or more chars other than line break chars.
Python demo:
import re
s = """Model Number : 123
Serial Number : 456"""
model_number = re.findall(r'Model Number\s*:.*',s)
print(model_number) # => ['Model Number : 123']
If you need to extract just the number use
r'Model Number\s*:\s*(\d+)'
See another regex demo and this Python demo.
Here, (\d+) will capture 1 or more digits and re.findall will only return these digits. Or, use it with re.search and once the match data object is obtained, grab it with match.group(1).
NOTE: If the string appears at the start of the string, use re.match. Or add ^ at the start of the pattern and use re.M flag (or add (?m) at the start of the pattern).
you can use strip() function
model_number.strip()
this will remove all white spaces

Starts with anything but not space and ends with extensions like (.png, .jpg, .mp4, .avi, .flv)

I need to get all files with media like extension( .png, .jpg, .mp4, .avi, .flv ) in a list by using regex.What i had tried is Below
import re
st = '''
/mnt/data/Content:
ManifestFile.txt kompass-tags_e2d5dac5ba548a1206b5d40f58e448e4 tmp_content
default_55a655f340908dce55d10a191b6a0140 price-tags_b3c756dda783ad0691163a900fb5fe15
/mnt/data/Content/default_55a655f340908dce55d10a191b6a0140:
LayoutFile_34450b33c8b44af409abb057ddedfdfe.txt blank_decommissioned.jpeg tmp_content
ManifestFile.txt blank_unregistered.png
/mnt/data/Content/default_55a655f340908dce55d10a191b6a0140/tmp_content:
/mnt/data/Content/kompass-tags_e2d5dac5ba548a1206b5d40f58e448e4:
0001111084948-kompass-LARGE.avi 0076738703404-kompass-LARGE.png LayoutFile_7c1b3793e49204982e0e41923303c17b.txt
0001111087321-kompass-LARGE.jpg 0076738703419-kompass-LARGE.mp4 ManifestFile.txt
0001111087325-kompass-LARGE.png 0076738703420-kompass-LARGE.png tmp_content
/mnt/data/Content/kompass-tags_e2d5dac5ba548a1206b5d40f58e448e4/tmp_content:
/mnt/data/Content/price-tags_b3c756dda783ad0691163a900fb5fe15:
0001111084948-consumer-large.png 0076738703404-consumer-large.png LayoutFile_a694b1e05d08705aaf4dd589ac61d493.txt
0001111087321-consumer-large.png 0076738703419-consumer-large.avi ManifestFile.txt
0001111087325-consumer-large.mp4 0076738703420-consumer-large.png tmp_content
/mnt/data/Content/price-tags_b3c756dda783ad0691163a900fb5fe15/tmp_content:
/mnt/data/Content/tmp_content:
'''
patt = '^.*(.png|.jpg|.gif|.bmp|.jpeg|.mp4|.avi|.flv)'
patt = '^.*$.png'
fList = re.findall(patt, st)
print fList
I have very less idea about regex please help.
The ^.*(.png|.jpg|.gif|.bmp|.jpeg|.mp4|.avi|.flv) pattern matches the start of a string, then any 0+ chars other than line break chars as many as possible and then the extensions with any single char before them (an unescaped . matches any char but a line break char). So, this can't work for you since . matches too much here and ^ only yields a match at the start of the string.
The ^.*$.png pattern only matches the start of the string, any 0+ chars other than line break chars then the end of string and any char + png - this is a pattern that will never match any string.
Judging by your description you need
patt = r'\S+\.(?:png|jpe?g|gif|bmp|mp4|avi|flv)\b'
See the regex demo.
Details
\S+ - 1+ non-whitespace chars
\. - a literal dot
(?:png|jpe?g|gif|bmp|mp4|avi|flv) - a non-capturing group (i.e. what it captures won't be part of the list returned by re.findall) matching any of the mentioned extenstions
\b - a word boundary (actually, it is optional, but it will make sure you match an extension above as a whole word).
See the Python demo:
import re
st = '<YOUR_STRING_HERE>'
patt = r'\S+\.(?:png|jpe?g|gif|bmp|mp4|avi|flv)\b'
fList = re.findall(patt, st)
for s in fList:
print(s)
yielding
blank_decommissioned.jpeg
blank_unregistered.png
0001111084948-kompass-LARGE.avi
0076738703404-kompass-LARGE.png
0001111087321-kompass-LARGE.jpg
0076738703419-kompass-LARGE.mp4
0001111087325-kompass-LARGE.png
0076738703420-kompass-LARGE.png
0001111084948-consumer-large.png
0076738703404-consumer-large.png
0001111087321-consumer-large.png
0076738703419-consumer-large.avi
0001111087325-consumer-large.mp4
0076738703420-consumer-large.png
You can use the RegEx \S+\.(?:png|jpg|gif|bmp|jpeg|mp4|avi|flv)
\S+ matches any non white-space char at least one time
\. matches a dot
(?: ... ) is a non capturing group
(png|jpg|gif|bmp|jpeg|mp4|avi|flv matches your defined extensions
Demo.
Try this:
patt = '[^ \n]+?\.(?:png|jpg|gif|bmp|jpeg|mp4|avi|flv)'
[^ \n] is a negated character class, allowing no spaces or newlines.
The dot (.) is a special character and needs to be escaped with a backslash.
Try it online here.

Return the next nth result \w+ after a hyphen globally

Just getting to the next stage of understanding regex, hoping the community can help...
string = These.Final.Hours-AUSVERSION.2013-TEST-TESTAGAIN-YIFY.cp(tt123456).MiLLENiUM.mp4
There are multiple test names preceded by a '-' hyphen which I derive from regex
\(?<=-)\w+\g
Result:
AUSVERSION
TEST
TESTAGAIN
YIFY
I can parse the very last result using greediness with regex \(?!.*-)(?<=-)\w+\g
Result:
YIFI (4th & last result)
Can you please help me parse either the 1st, 2nd, or 3rd result Globally using the same string?
In Python, you can get these matches with a simple -\s*(\w+) regex and re.findall and then access any match with the appropriate index:
See IDEONE demo:
import re
s = 'These.Final.Hours-AUSVERSION.2013-TEST-TESTAGAIN-YIFY.cp(tt123456).MiLLENiUM.mp4'
r = re.findall(r'-\s*(\w+)', s)
print(r[0]) # => AUSVERSION
print(r[1]) # => TEST
print(r[2]) # => TESTAGAIN
print(r[3]) # => YIFY
The -\s*(\w+) pattern search for a hyphen, followed with 0+ whitespaces, and then captures 1+ digits, letters or underscores. re.findall only returns the texts captured with capturing groups, so you only get those Group 1 values captured with (\w+).
To get these matches one by one, with re.search, you can use ^(?:.*?-\s*(\w+)){n}, where n is the match index you want. Here is a regex demo.
A quick Python demo (in real code, assign the result of re.search and only access Group 1 value after checking if there was a match):
s = "These.Final.Hours-AUSVERSION.2013-TEST-TESTAGAIN- YIFY.cp(tt123456).MiLLENiUM.mp4"
print(re.search(r'^(?:.*?-\s*(\w+))', s).group(1))
print(re.search(r'^(?:.*?-\s*(\w+)){2}', s).group(1))
print(re.search(r'^(?:.*?-\s*(\w+)){3}', s).group(1))
print(re.search(r'^(?:.*?-\s*(\w+)){4}', s).group(1))
Explanation of the pattern:
^ - start of string
(?:.*?-\s*(\w+)){2} - a non-capturing group that matches (here) 2 sequences of:
.*? - 0+ any characters other than a newline (since no re.DOTALL modifier is used) up to the first...
- - hyphen
\s* - 0 or more whitespaces
(\w+) - Group 1 capturing 1+ word characters (letters, digits or underscores).

Categories