Reputation: 131
I have a problem with regex, using preg_match_all(), to match something of a variable length.
What I am trying to match is the traffic condition after the word 'Congestion' What I came up with is this regex pattern:
Congestion\s*:\s*(?P<congestion>.*)
It would however, extract the first instance all the way to the end of the entire subject, since .* would match everything. But that's not what I want though, I would like it to match separately as 3 instances.
Now since the words behind Congestion could be of variable length, I can't really predict how many words and spaces are in between to come up with a stricter \w*\s*\w* match etc.
Any clues on how I can proceed from here?
Highway : Highway 26
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow from Smith St to Alice Springs St
Highway : Princes Highway
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow at the Flinders St / Elizabeth St intersection
Highway : Eastern Freeway
Datetime : 18-Oct-2010 05:19 PM
Congestion : Traffic is slow from Prince St to Queen St
EDIT FOR CLARITY
These very nicely formatted texts here, are actually received via a very poorly formatted html email. It contains random line breaks here and there eg "Congestion : Traffic\n is slow from Prince\nSt to Queen St".
So while processing the emails, I stripped off all the html codes and the random line breaks, and json_encode() them into one very long single-line string with no line break...
Upvotes: 2
Views: 646
Reputation: 683
You can try a minimal match:
Congestion\s*:\s*(?P<congestion>.*?)
This would result in returning zero characters in the named group 'congestion' unless you could match something immediately after the congestion string.
So, this could be fixed if "Highway" always starts the traffic condition records:
Congestion\s*:\s*(?P<congestion>.*?)Highway\s*:
If this works (I have not checked it), then the first records are matched but the last record is not! This could be easily fixed by appending the text 'Highway :' at the end of the input string.
Upvotes: 2
Reputation: 59461
Congestion\s*:\s*Traffic is\s*(?P<c1>[^\n]*)\s*from\s*(?P<c2>[^\n]*)\s*to\s*(?P<c3>[^\n]*)$
Upvotes: 2
Reputation: 545963
Usually, regex matching is line-based. Regex assumes that your string is a single line. You can use the “m
” (PCRE_MULTILINE) flag to change that behaviour. Then you can tell PHP to match only to the end of the line:
preg_match('/^Congestion\s*:\s*(?P<congestion>.*)$/m', $subject, $matches);
There are two things to notice: first, the pattern was modified to include line-begin (^
) and line-end ($
) markers. Secondly, the pattern now carries the m
modifier.
Upvotes: 4