Extracting words inside bracket using regex in python

Viewed 227

What will be the regular expression for the following pattern shown in the image below? (Note: there are many more tags and in no specific order.there is a lot of information between the tags that dont follow this pattern. i just need to extract the information within the large bracket)Data pattern

I need to seperate the data inside the large bracket seperately. for e.g. severity and 2. So far, i have only been able to collect the data having such large brackets using r'\[([^]]*)\]'. how do i seperate them? and please do explain. I am familiar with regex symbols but cannot work my head around with these complicated patterns.

5 Answers

You may use

import re

rx = re.compile("""\[(?P<key>[^\]\[\s]+)(?:\s+"(?P<value>[^"]+)")?\]""")
text = """lorem ipsum [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] lorem ipsum"""

result = {m.group('key'): m.group('value') for m in rx.finditer(text)}
print(result)

Which yields

{'severity': '2', 'maturity': '0', 'accuracy': '0', 'tag': 'application-multi'}

See a demo on regex101.com.

import re
value = '[severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"]'
print(re.findall(r'\[(\w+)\s+"([^"]+)"\]', value))

This will give you the keys and values: [('severity', '2'), ('maturity', '0'), ('accuracy', '0'), ('tag', 'application-multi')]

If you want a dictionary that's easy: print(dict(re.findall(r'\[(\w+)\s+"([^"]+)"\]', value)))

Now the explanation of the regular expression. First looking for an opening bracket: \[ (escaped). Then catch the word characters: (\w+). Then one or more spaces followed by a double quote: \s+". Then we catch everything that's not a double quote: ([^"]+). Finally find the double quote followed by the closing bracket: "\].

I suggest using re.finditer to loop over matches, and use these to create a dictionary:

import re

text = '[severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"]'

tags = {m.group(1): m.group(2)
        for m in re.finditer('\[(.*?)\s*"(.*?)"\]', text)}

print(tags)
{'severity': '2', 'ver': '', 'maturity': '0', 'accuracy': '0', 'tag': 'application-multi'}

This makes it convenient to extract data items, but it does of course assume that keys are unique. If they are not, then you could instead use for example a list of 2-tuples:

[(m.group(1), m.group(2))
 for m in re.finditer('\[(.*?)\s*"(.*?)"\]', text)]
[('severity', '2'), ('ver', ''), ('maturity', '0'), ('accuracy', '0'), ('tag', 'application-multi')]

If you want both the first and second word of each pair:

>>> import re
>>> inp = '[severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"]'
>>> list_of_tuples = re.findall(r'\[(\w+) \"(.*?)\"\]', inp)
>>> list_of_tuples
[('severity', '2'), ('ver', ''), ('maturity', '0'), ('accuracy', '0'), ('tag', 'application-multi')]

Use

\[([^][]+?)(?:\s+"([^"]*)")?]

See proof

Explanation

--------------------------------------------------------------------------------
  \[                       '['
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    [^][]+?                  any character except: ']', '[' (1 or
                             more times (matching the least amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \s+                      whitespace (\n, \r, \t, \f, and " ") (1
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    "                        '"'
--------------------------------------------------------------------------------
    (                        group and capture to \2:
--------------------------------------------------------------------------------
      [^"]*                    any character except: '"' (0 or more
                               times (matching the most amount
                               possible))
--------------------------------------------------------------------------------
    )                        end of \2
--------------------------------------------------------------------------------
    "                        '"'
--------------------------------------------------------------------------------
  )?                       end of grouping
--------------------------------------------------------------------------------
  ]                        ']'

Python code:

import re
expression = r'\[([^][]+?)(?:\s+"([^"]*)")?]'
test = 'lorem ipsum [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] lorem ipsum'
print( {x.group(1):x.group(2) for x in re.finditer(expression, test)} )

Result:

{'severity': '2', 'ver': '', 'maturity': '0', 'accuracy': '0', 'tag': 'application-multi'}
Related