Regex: expression to match 'name1: A=a name2:B=b name3:C=c d'

Viewed 116

I am using the re module's re.compile() of Python to split name1:A=a name2:B=b name3:C=c d into:

name1 A=a, name2 B=b, name3 C=c d

This is my regex for now:

(\w+): (A|B|C)(=[\w+\s*\w*]+)

But it ends up giving me the output as:

name1: A=a name2: B=b name3: C=c d

The bold text is the text that it is capturing. The words A,B and C are from a predefined list of headings i.e. only these will occur before an '=' sign.

4 Answers

Instead of splitting you could try to match the relevant parts:

import re

text = "name1:A=a name2:B=b name3:C=c d"

rx = re.compile(r'\w+:(?:\w+(?:=\w+)?(?:\s+|$))+')

for match in rx.finditer(text):
    name, rest = match.group(0).split(":")
    print("{}, {}".format(name, rest))

This yields

name1, A=a 
name2, B=b 
name3, C=c d

See a demo for the expression on regex101.com.

You need to indicate the edge to the next match. Here line feed or end of text did the job.

(\w+): [ABC](=\w+\s*\w*)(?:\n|$)

By the way, the source contains a "," while in your regex there is a ":" used after name.

Here a solution for a one line string.

(\w+): (A|B|C)(=\w+\s*\w*?\(?:\s+|$))

This doesn't answer your question exactly but it's good to know that you could get what you want without using regex:

import itertools

my_string =  "name1 A:a name2 B:b name3 C:c  d"
# split on whitespaces
split_string = my_string.split()
# get only the even elements
evens = split_string[0::2]
# get only the odd elements
odds = split_string[1::2]
# get the A=a format you want
new_odds = [odd.replace(":", "=") for odd in odds]
# zip the lists together, without losing any elements from the longer list
zipped = itertools.zip_longest(evens, new_odds)
# make this zip a list for us to view it
zipped_as_list = [x for x in zipped]
# look at what we made
print(zipped_as_list)

I don't know exactly what shape you want your data at the end, or how that trailing d is meant to be treated.

If you are limited to use split, please use below regex.

\s(?=\w+:)|:

Example

import re
text="name1:A=a name2:B=b name3:C=c d"
print(re.split(r"\s(?=\w+:)|:",text))

Output

['name1', 'A=a', 'name2', 'B=b', 'name3', 'C=c d']
Related