Regex - Extracting text after a hyphen into a dictionary in Python

Viewed 205

I am trying to extract data from a log into a dictionary. This is what the first line looks like:

146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622

I've managed to extract the IP into a dictionary, but when trying to get the user name (after the hyphen) I get this output:

{'host': '146.204.224.152', 'user_name': ' '}

This is the code I am using:

for item in re.finditer("(?P<host>[0-9]+(?:\.[0-9]+){3})(P<user_name>(?<=- )*\s)", logdata):
print(item.groupdict())

I'm a noob to regex. Any advice as to what I'm doing wrong?

The output I want should look like this:

{'host': '146.204.224.152', 'user_name': 'feest6811'}
1 Answers

First of all, there is a typo, (P<user_name> must be (?P<user_name>.

Regular expression engine parses a string from left to right (at least by default and there are not so many regex libraries supporting the right to left parsing). The string is read char by char, and tries to match these chars with the pattern. It cannot skip parts of the string between the consuming subpatterns (i.e. those that make the regex index advance, i.e. non-lookarounds). So, the (?<=- )* is a positive lookbehind that requires a - and space to be immediately to the left of the current location, zero or more times due to * after it. This * quantifier makes the whole idea of using the lookbehind here meaningless, since it stops requiring anything. So, all this does it capturing a whitespace with \s.

All you need is to consume the part between the date and the user, say, with \s+-\s+ or \s+\S+\s+:

(?P<host>[0-9]+(?:\.[0-9]+){3})\s+-\s+(?P<user_name>\S+)

See the regex demo.

The \s+-\s+ matches a - enclosed with one or more whitespaces, and \s+\S+\s+ matches one or more non-whitespace chars enclosed with one or more whitespaces.

Related