If your problem is really just this simple, you don't need regex:
s[s.find("(")+1:s.find(")")]
Answer from tkerwin on Stack OverflowIf your problem is really just this simple, you don't need regex:
s[s.find("(")+1:s.find(")")]
Use re.search(r'\((.*?)\)',s).group(1):
>>> import re
>>> s = u'abcde(date=\'2/xc2/xb2\',time=\'/case/test.png\')'
>>> re.search(r'\((.*?)\)',s).group(1)
u"date='2/xc2/xb2',time='/case/test.png'"
regex - python - Return Text Between Parenthesis - Stack Overflow
Extract string within parentheses - PYTHON - Stack Overflow
Extract text between parentheses
python - Find something between parentheses - Stack Overflow
Without regexp:
[p.split(')')[0] for p in s.split('(') if ')' in p]
Output:
['W', 'indo', 'ws ', 'XP', ', ', 'with ', 'the ', 'fragment ', 'enlar', 'ged ', 'for ', 'clarity ', 'on ', 'Fig. ']
findall looks like your friend here. Don't you just want:
re.findall(r'\(.*?\)',readstream)
returns:
['(W)',
'(indo)',
'(ws )',
'(XP)',
'(, )',
'(with )',
'(the )',
'(fragment )',
'(enlar)',
'(ged )',
'(for )',
'(clarity )',
'(on )',
'(Fig. )']
Edit:
as @vikramis showed, to remove the parens, use: re.findall(r'\((.*?)\)', readstream). Also, note that it is common (but not requested here) to trim trailing whitespace with something like:
re.findall(r'\((.*?) *\)', readstream)
You can use a simple regex to catch everything between the parenthesis:
>>> import re
>>> s = 'Name(something)'
>>> re.search('\(([^)]+)', s).group(1)
'something'
The regex matches the first "(", then it matches everything that's not a ")":
\(matches the character "(" literally- the capturing group
([^)]+)greedily matches anything that's not a ")"
as an improvement on @Maroun Maroun 's answer:
re.findall('\(([^)]+)', s)
it finds all instances of strings in between parentheses
You should group alternations like (?:LD|OR), and to match any chars other than ( and ) you may use [^()]* rather than .+ (.+ matches any chars, as many as possible, hence it matches across parentheses).
Here is a Python demo:
import re
Text = 'LD(_030S.F.IN)OR(_080T_SAF_OUT)COIL(xxSF[4].Flt[120].0)'
m = re.search(r'(?:OR|LD)\([^()]*\)COIL\(xxSF\[\d+]\.Flt\[\d+]\.\d+', Text)
if m:
print(m.group()) # => OR(_080T_SAF_OUT)COIL(xxSF[4].Flt[120].0
Pattern details
(?:OR|LD)- a non-capturing group matchingORorLD\(- a(char[^()]*- a negated character class matching 0+ chars other than(and)\)COIL\(xxSF\[-)COIL(xxSF[substring\d+- 1+ digits]\.Flt\[-].Flt[substring\d+]\.\d+- 1+ digits,].substring and 1+ digits
See the regex demo.
TIP Add a \b before (?:OR|LD) to match them as whole words (not as part of NOR and NLD).
Thanks, I am capturing everything which I want. Just something else to filter. Take a look to some Outputs:
OR(_1B21_A53021_2_En)OR(_1_A21_Z53021_2)COIL(xxSF[9].Flt[15].3);
LD(_1B21_A53021_2_En)LD(_1_A21_Z53021_2)COIL(xxSF[9].Flt[15].3);
I only want to capture the last one "LD" or "OR" as follow:
OR(_1_A21_Z53021_2)COIL(xxSF[9].Flt[15].3);
LD(_1_A21_Z53021_2)COIL(xxSF[9].Flt[15].3);
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'
string = "Will Ferrell (Nick Halsey), Rebecca Hall (Samantha), Michael Pena (Frank Garcia)"
import re
pat = re.compile(r'([^(]+)\s*\(([^)]+)\)\s*(?:,\s*|$)')
lst = [(t[0].strip(), t[1].strip()) for t in pat.findall(string)]
The compiled pattern is a bit tricky. It's a raw string, to make the backslashes less insane. What it means is: start a match group; match anything that isn't a '(' character, any number of times as long as it is at least once; close the match group; match a literal '(' character; start another match group; match anything that isn't a ')' character, any number of times as long as it is at least once; close the match group; match a literal ')' character; then match any white space (including none); then something really tricky. The really tricky part is a grouping that doesn't form a match group. Instead of starting with '(' and ending with ')' it starts with "(?:" and then again ends with ')'. I used this grouping so I could put a vertical bar in to allow two alternate patterns: either a comma matches followed by any amount of white space, or else the end of the line was reached (the '$' character).
Then I used pat.findall() to find all the places within string that the pattern matches; it automatically returns tuples. I put that in a list comprehension and called .strip() on each item to clean off white space.
Of course, we can just make the regular expression even more complicated and have it return names that already have white space stripped off. The regular expression gets really hairy, though, so we will use one of the coolest features in Python regular expressions: "verbose" mode, where you can sprawl a pattern across many lines and put comments as you like. We are using a raw triple-quote string so the backslashes are convenient and the multiple lines are convenient. Here you go:
import re
s_pat = r'''
\s* # any amount of white space
([^( \t] # start match group; match one char that is not a '(' or space or tab
[^(]* # match any number of non '(' characters
[^( \t]) # match one char that is not a '(' or space or tab; close match group
\s* # any amount of white space
\( # match an actual required '(' char (not in any match group)
\s* # any amount of white space
([^) \t] # start match group; match one char that is not a ')' or space or tab
[^)]* # match any number of non ')' characters
[^) \t]) # match one char that is not a ')' or space or tab; close match group
\s* # any amount of white space
\) # match an actual required ')' char (not in any match group)
\s* # any amount of white space
(?:,|$) # non-match group: either a comma or the end of a line
'''
pat = re.compile(s_pat, re.VERBOSE)
lst = pat.findall(string)
Man, that really wasn't worth the effort.
Also, the above preserves the white space inside the names. You could easily normalize the white space, to make sure it is 100% consistent, by splitting on white space and rejoining with spaces.
string = ' Will Ferrell ( Nick\tHalsey ) , Rebecca Hall (Samantha), Michael\fPena (Frank Garcia)'
import re
pat = re.compile(r'([^(]+)\s*\(([^)]+)\)\s*(?:,\s*|$)')
def nws(s):
"""normalize white space. Replaces all runs of white space by a single space."""
return " ".join(w for w in s.split())
lst = [tuple(nws(item) for item in t) for t in pat.findall(string)]
print lst # prints: [('Will Ferrell', 'Nick Halsey'), ('Rebecca Hall', 'Samantha'), ('Michael Pena', 'Frank Garcia')]
Now the string has silly white space: multiple spaces, a tab, and even a form feed ("\f") in it. The above cleans it up so that names are separated by a single space.
A good place for regular expressions:
>>> import re
>>> pat = "([^,\(]*)\((.*?)\)"
>>> re.findall(pat, "Will Ferrell (Nick Halsey), Rebecca Hall (Samantha), Michael Pena (Frank Garcia)")
[('Will Ferrell ', 'Nick Halsey'), (' Rebecca Hall ', 'Samantha'), (' Michael Pena ', 'Frank Garcia')]
I think your problem is that your .* operators are being greedy - they will consume as much as they can if you don't put a ? after them: .*?. Also, note that since you want the parentheses, you shouldn't need the lookahead/lookbehind operations; they will exclude the parentheses they find.
Instead of fully debugging your regex, I decided to just rewrite it:
>>> import re
>>> foo ='((peach W/O juice) OR apple OR (pear W/O water) OR kiwi OR (lychee AND sugar) OR (pineapple W/O salt))'
>>> regex = '\([a-zA-Z ]*?W/O.*?\)'
>>> re.findall(regex, foo)
['(peach W/O juice)', '(pear W/O water)', '(pineapple W/O salt)']
Here's the breakdown:
\( captures the leading parentheses - note that it's escaped
[a-zA-Z ] captures all alphabetical characters and a space (note the space after Z before the closing bracket) I used this instead of . so that no other parentheses will be captured. Using the period operator would cause (lychee AND sugar) OR (pineapple W/O salt) to be captured as one match.
*? the * causes the characters in the bracket to match 0 or more times, but the ? says to only capture as many as you need to make a match
W/O captures the "W/O" that you're looking for
.*? captures any more characters (again, non-greedy because of ?)
\) captures the trailing parenthesese
Since you want to include parenthesis in the result, you don't need to use lookarounds. You can use a character class that exclude the closing parenthesis. In this way, you are sure that W/O is between parenthesis:
re.findall(r'\([^()]* W/O [^)]*\)', foo)