I have been trying to get the separate groups from the below string using regex in PCRE:
drop = blah blah blah something keep = bar foo nlah aaaa rename = (a=bd=e) obs=4 where = (foo > 45 and bar == 35)
Groups I am trying to make is like:
1. drop = blah blah blah something
2. keep = bar foo nlah aaaa
3. rename = (a=b d=e)
4. obs=4
5. where = (foo > 45 and bar == 35)
I have written a regex using recursion but for some reason recursion is partially working for selecting multiple words after drop
like it's selecting just first 3 words (blah blah blah) and not the 4th one. I have looked through various stackoverflow questions and have tried using positive lookahead also but this is the closest I could get to and now I am stuck because I am unable to understand what I am doing wrong.
The regex that I have written: (?i)(drop|keep|where|rename|obs)\\s*=\\s*((\\w+|\\d+)(\\s+\\w+)(?4)|(\\((.*?)\\)))
Same can be seen here: RegEx Demo .
Any help on this or understanding what I am doing wrong is appreciated.
You could use the newer regex
module with DEFINE
:
(?(DEFINE)
(?<key>\w+)
(?<sep>\s*=\s*)
(?<value>(?:(?!(?&key)(?&sep))[^()=])+)
(?<par>\((?:[^()]+|(?&par))+\))
)
(?P<k>(?&key))(?&sep)(?P<v>(?:(?&value)|(?&par)))
See a demo on regex101.com .
In Python
this could be:
import regex as re
data = """
drop = blah blah blah something keep = bar foo nlah aaaa rename = (a=b d=e) obs=4 where = (foo > 45 and bar == 35)
"""
rx = re.compile(r'''
(?(DEFINE)
(?<key>\w+)
(?<sep>\s*=\s*)
(?<value>(?:(?!(?&key)(?&sep))[^()=])+)
(?<par>\((?:[^()]+|(?&par))+\))
)
(?P<k>(?&key))(?&sep)(?P<v>(?:(?&value)|(?&par)))''', re.X)
result = {m.group('k').strip(): m.group('v').strip()
for m in rx.finditer(data)}
print(result)
And yields
{'drop': 'blah blah blah something', 'keep': 'bar foo nlah aaaa', 'rename': '(a=b d=e)', 'obs': '4', 'where': '(foo > 45 and bar == 35)'}
You can use a branch reset group solution:
(?i)\b(drop|keep|where|rename|obs)\s*=\s*(?|(\w+(?:\s+\w+)*)(?=\s+\w+\s+=|$)|\((.*?)\))
See the PCRE regex demo
Details
(?i)
- case insensitive mode on \\b
- a word boundary (drop|keep|where|rename|obs)
- Group 1: any of the words in the group \\s*=\\s*
- a =
char enclosed with 0+ whitespace chars (?|
- start of a branch reset group:
(\\w+(?:\\s+\\w+)*)
- Group 2: one or more word chars followed with zero or more repetitions of one or more whitespaces and one or more word chars (?=\\s+\\w+\\s+=|$)
- up to one or more whitespaces, one or more word chars, one or more whitespaces, and =
, or end of string |
- or
\\((.*?)\\)
- (
, then Group 2 capturing any zero or more chars other than line break chars, as few as possible and then )
)
- end of the branch reset group. See Python demo :
import regex
pattern = r"(?i)\b(drop|keep|where|rename|obs)\s*=\s*(?|(\w+(?:\s+\w+)*)(?=\s+\w+\s+=|$)|\((.*?)\))"
text = "drop = blah blah blah something keep = bar foo nlah aaaa rename = (a=b d=e) obs=4 where = (foo > 45 and bar == 35)"
print( [x.group() for x in regex.finditer(pattern, text)] )
# => ['drop = blah blah blah something', 'keep = bar foo nlah aaaa', 'rename = (a=b d=e)', 'obs=4', 'where = (foo > 45 and bar == 35)']
print( regex.findall(pattern, text) )
# => [('drop', 'blah blah blah something'), ('keep', 'bar foo nlah aaaa'), ('rename', 'a=b d=e'), ('obs', '4'), ('where', 'foo > 45 and bar == 35')]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.