I got all of them to match using this (You'll need to add the case-insensitive flag):
(^[a-z][a-z\'&\(\) ]+\bv\b[a-z&\'\(\) ]+(?:.*?) \[?\d+ \w+ \d{4}\]?)
Regex Demo
Explanation:
(Begin capture group[a-z\'&\(\) ]+Match one or more of the characters in this group\bMatch a word boundaryvMatch the character'v'literally\bMatch a word boundary[a-z&\'\(\) ]+Match one or more of the characters in this group(?:Begin non-capturing group.*?Match anything
)End non-capturing group\[?\d+ \w+ \d{4}\]?Match a date, optionally surrounded by brackets
)End capture group
I got all of them to match using this (You'll need to add the case-insensitive flag):
(^[a-z][a-z\'&\(\) ]+\bv\b[a-z&\'\(\) ]+(?:.*?) \[?\d+ \w+ \d{4}\]?)
Regex Demo
Explanation:
(Begin capture group[a-z\'&\(\) ]+Match one or more of the characters in this group\bMatch a word boundaryvMatch the character'v'literally\bMatch a word boundary[a-z&\'\(\) ]+Match one or more of the characters in this group(?:Begin non-capturing group.*?Match anything
)End non-capturing group\[?\d+ \w+ \d{4}\]?Match a date, optionally surrounded by brackets
)End capture group
How to make Square brackets optional, can be achieved like this:
[\[]* with the * it makes the opening [ optional.
A few recommendations if I may:
This
\d\d\d\dcould be also expressed like this as well\d{4}[v|V]in regex what is inside the[]is already one or other|is not necessary[vV]
And here is what an online demo
python - Regex string between square brackets only if '.' is within string - Stack Overflow
regex - Get the string within brackets in Python - Stack Overflow
regex - Regular Expression to match numbers in square brackets in python - Stack Overflow
python - Regex for matching square brackets and number - Stack Overflow
You might write a pattern matching [...] and then repeat 1 or more times a . and again [...]
\[[^][]*](?:\.\[[^][]*])+
Explanation
\[[^][]*]Match from[...]using a negated character class(?:Non capture group to repeat as a whole part\.\[[^][]*]Match a dot and again[...]
)+Close the non capture group and repeat 1+ times
See a regex demo.
To get multiple matches, you can use re.findall
import re
pattern = r"\[[^][]*](?:\.\[[^][]*])+"
s = ("CASE[Data Source].[Week] = 'THIS WEEK'\n"
"CASE[Data Source].[Week] = 'THIS WEEK'")
print(re.findall(pattern, s))
Output
['[Data Source].[Week]', '[Data Source].[Week]']
If you also want the values of between square brackets when there is not dot, you can use an alternation with lookaround assertions:
\[[^][]*](?:\.\[[^][]*])+|(?<=\[)[^][]*(?=])
Explanation
\[[^][]*](?:\.\[[^][]*])+The same as the previous pattern|Or(?<=\[)[^][]*(?=])Match[...]asserting[to the left and]to the right
See another regex demo
I think an alternative approach could be:
import re
pattern = re.compile("(\[[^\]]*\]\.\[[^\]]*\])")
print(pattern.findall(sss))
OUTPUT
['[Data Source].[Week]']
How about:
import re
s = "alpha.Customer[cus_Y4o9qMEZAugtnW] ..."
m = re.search(r"\[([A-Za-z0-9_]+)\]", s)
print m.group(1)
For me this prints:
cus_Y4o9qMEZAugtnW
Note that the call to re.search(...) finds the first match to the regular expression, so it doesn't find the [card] unless you repeat the search a second time.
Edit: The regular expression here is a python raw string literal, which basically means the backslashes are not treated as special characters and are passed through to the re.search() method unchanged. The parts of the regular expression are:
\[matches a literal[character(begins a new group[A-Za-z0-9_]is a character set matching any letter (capital or lower case), digit or underscore+matches the preceding element (the character set) one or more times.)ends the group\]matches a literal]character
Edit: As D K has pointed out, the regular expression could be simplified to:
m = re.search(r"\[(\w+)\]", s)
since the \w is a special sequence which means the same thing as [a-zA-Z0-9_] depending on the re.LOCALE and re.UNICODE settings.
You could use str.split to do this.
s = "<alpha.Customer[cus_Y4o9qMEZAugtnW] active_card=<alpha.AlphaObject[card]\
...>, created=1324336085, description='Customer for My Test App',\
livemode=False>"
val = s.split('[', 1)[1].split(']')[0]
Then we have:
>>> val
'cus_Y4o9qMEZAugtnW'
use this regex expression (\[[,\d\s ]*)11([,\d\s ]*\]) for retrieving all the 11's in the text
have a look at the example I uploaded https://regex101.com/r/lN8mA6/1
Since in Python we cannot use variable-width lookbehinds with standard re module, you can use capturing groups, and then check the index of the group.
Sample code for capturing 11:
pattern = re.compile(r'(\[[^\]]*)\b(11)\b(?=[^\]]*\])') # for 11
text = 'Gabrilovich and Markovitch [11, 12] propose a method to use conditional random fields [6] as a training process.....'
result = re.search(pattern, text)
if result:
print result.start(2)
Result: 28.
Note that I am using word boundaries around 11 to only match 11, and not 111 or 112.
Hi there,
I'm trying to match the inside of the most "external" brackets i.e. from Sum(x3, (x0, x1, x2)) I'd like to extract Sum(x3, (x0, x1, x2)).
I tried
import re
expr = "Sum(x3, (x0, x1, x2))"
match = re.search("(\((.*?)\))", expr)
bracket_part = match.group(1)
print(bracket_part)
yet this matches only Sum(x3, (x0, x1, x2). Of course one could simply add a ) yet it would be nice to extract (x) from expression like sin(x).
Do guys have an idea how to tell regex to match up until the very last closing bracket? Thanks a lot in advance!
What you need is re.sub. Note that both square brackets and pipes are meta-characters so they need to be escaped.
re.sub(r'\[\[(?:[^\]|]*\|)?([^\]|]*)\]\]', r'\1', line)
The \1 in the replacement string refers to what was matched inside the parentheses, that do not start with ?: (i.e. in any case the text you want to have).
There are two caveats. This allows for only a single pipe between the opening and closing brackets. If there are more than one you would need to specify whether you want everything after the first or everything after the last one. The other caveat is that single ] between opening and closing brackets are not allowed. If that is a problem, there would still be a regex solution but it would be considerably more complicated.
For a full explanation of the pattern:
\[\[ # match two literal [
(?: # start optional non-capturing subpattern for pre-| text
[^\]|] # this looks a bit confusing but it is a negated character class
# allowing any character except for ] and |
* # zero or more of those
\| # a literal |
)? # end of subpattern; make it optional
( # start of capturing group 1 - the text you want to keep
[^\]|]* # the same character class as above
) # end of capturing group
\]\] # match two literal ]
You can use re.sub to just find everything between [[ and ]]and I think it's slightly easier to pass in a lambda function to do the replacement (to take everything from the last '|' onwards)
>>> import re
>>> re.sub(r'\[\[(.*?)\]\]', lambda L: L.group(1).rsplit('|', 1)[-1], line)
'is the combination of the code names for Herbicide Orange (HO) and Agent LNX, one of the herbicides and defoliants used by the U.S. military as part of its herbicidal warfare program, Operation Ranch Hand, during the Vietnam War from 1961 to 1971.'
I am trying to test if a line contains a string of text that contains an open square bracket, but when I use
headerrx = re.compile('^\[Event ') it throws an error:
/filter_pgn.py:22: SyntaxWarning: invalid escape sequence '\['
headerrx = re.compile('^\[Event ')
re.error: unterminated character set at position 1Any idea what I'm doing wrong? The text I'm trying to parse will look like:
[Event "name of event"]
To expand on the explanation of the regex used by Avinash in his answer:
Category:([^\[\]]*) consists of several parts:
Category:which matches the text "Category:"(...)is a capture group meaning roughly "the expression inside this group is a block that I want to extract"[^...]is a negated set which means "do not match any characters in this set".\[and\]match "[" and "]" in the text respectively.*means "match zero or more of the preceding regex defined items"
Where I have used ... to indicate that I removed some characters that were not important for the explanation.
So putting it all together, the regex does this:
Finds "Category:" and then matches any number (including zero) characters after that that are not the excluded characters "[" or "]". When it hits an excluded character it stops and the text matched by the regex inside the (...) part is returned. So the regex does not actually look for "[[" or "]]" as you might expect and so will match even if they are left out. You could force it to look for the double square brackets at the beginning and end by changing it to \[\[Category:([^\[\]]*)\]\].
For the second regex, Category:[^\[\]]*, the capture group (...) is excluded, so Python returns everything matched which includes "Category:".
Seems like you want something like this,
>>> str = "[[Category:Political culture]]\n\n [[Category:Political ideologies]]\n\n"
>>> re.findall(r'Category:([^\[\]]*)', str)
['Political culture', 'Political ideologies']
>>> re.findall(r'Category:[^\[\]]*', str)
['Category:Political culture', 'Category:Political ideologies']
By default re.findall will print only the strings which are matched by the pattern present inside a capturing group. If no capturing group was present, then only the findall function would return the matches in list. So in our case , this Category: matches the string category: and this ([^\[\]]*) would capture any character but not of [ or ] zero or more times. Now the findall function would return the characters which are present inside the group index 1.
You can match the following regular expression.
^(?P<timestamp>[JFMASOND][a-z]{2} [0123]\d [012]\d(?::[0-5]\d){2}\.\d{6}\b) (?P<levelname>[A-Z]) +(?:[A-Z]+: +)?(?:\[+(?P<source>[A-Za-z]+)\]+)? *(?P<message>.+)
Demo
Notice that I've made the capture group source optional.
Depending on requirements some adjustments may need to be made. I assumed, for example, that the source capture group would contain a single word and if there were non-spaces between the levelname and source (or message) it would be comprised of one or more capital letters followed by a colon, as in the second example ('ERR:'). I've also made assumptions about how rigorous the timestamp format must be specified and which capture groups should be made optional. These were of course just guesses about the specification as they were not spelled out in the question.
The regular expression can be broken down as follows. Note that I have put individual spaces in character classes ([ ]) merely to make them visible to the reader. I've tested this with Python (for which named character classes are written (?P<name>....), but it would work in Ruby as well.
^ # match beginning of string
(?P<timestamp> # begin 'timestamp' capture group
[JFMASOND] # match a cap letter in the char class
[a-z]{2} # match two lowercase letters
[ ] # match a space
[0123]\d # match a digit in the char class then any digit
[ ] # match a space
[012]\d # match a digit in the char class then any digit
(?: # begin a non-capture group
: # match a colon
[0-5]\d # match a digit in the char class then any digit
){2} # end non-capture group and execute it twice
\. # match a period
\d{6} # match 6 digits
\b # match a word boundary
) # end timestamp capture group
(?P<levelname> # begin 'levelname' capture group
[A-Z])[ ]+ # match a capital letter then >= 1 spaces
) # end 'levelname' capture group
(?:[A-Z]+:[ ]+)? # optionally match >= 1 capital letters
# then >= 1 spaces
(?: # begin non-capture group
\[+ # match one or more left brackets
(?P<source> # begin capture group 'source'
[A-Za-z]+ # match >= 1 chars in char class
) # end capture group 'source'
\]+ # match one or more right brackets
)? # end non-capture group and make optional
[ ]* # match >= 0 spaces
(?P<message>.+) # match rest of line and save to capture
# group 'message'
I think this is what you want
^(?<timestamp>[a-zA-Z]{3} [0-9]{1,2} [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\.[0-9]{1,6}) (?<levelname>[A-Z]) ?(ERR:)? ?(\[*(?<source>\w*)\]*) (?<message>.*)
brackets should wrap the source field.