Using regex (Python) I want to capture a group \d-. ? that is immediately followed by another pattern \sLEFT|\sRIGHT|\sUP.
Here is my test set (from http://nflsavant.com/about.php):
(9:03) (SHOTGUN) 30-J.RICHARD LEFT GUARD PUSHED OB AT MIA 9 FOR 18 YARDS (29-BR.JONES; 21-E.ROWE).
(1:06) 69-R.HILL REPORTED IN AS ELIGIBLE. 33-D.COOK LEFT GUARD TO NO 4 FOR -3 YARDS (56-D.DAVIS; 93-D.ONYEMATA).
(3:34) (SHOTGUN) 28-R.FREEMAN LEFT TACKLE TO LAC 37 FOR 6 YARDS (56-K.MURRAY JR.).
(1:19) 22-L.PERINE UP THE MIDDLE TO CLE 43 FOR 2 YARDS (54-O.VERNON; 51-M.WILSON).
My best attempt is (\d*-. ?)(?=\sLEFT|\sRIGHT|\sUP), which works unless other characters appear between a matching capture group and my positive lookahead. In the second line of my test set this expression captures "69-R.HILL REPORTED IN AS ELIGIBLE. 33-D.COOK." instead of the desired "33-D.COOK".
My inputs are also saved on regex101, here: https://regex101.com/r/tEyuiJ/1
How can I modify (or completely rewrite) my regex to only capture the group immediately followed by my exact positive lookahead with no extra characters between?
CodePudding user response:
If you want a capture group without any lookarounds:
\b(\d -\S*)\s(?:LEFT|RIGHT|UP)\b
Explanation
\bA word boundary to prevent a partial word match(\d -\S*)Capture group 1, match 1 digits-and optional non whitespace characters\sMatch a single whitespace character(?:LEFT|RIGHT|UP)Match any of the alternatives\bA word boundary
See the capture group value on regex101.
CodePudding user response:
To prevent skipping over digits, use \D non-digit (upper is negated \d).
\b(\d -\D ?)\s(?:LEFT|RIGHT|UP)
Further added a word boundary and changed the lookahead to a group.
CodePudding user response:
This is why you should be careful about using . to match anything and everything unless it's absolutely necessary. From the example you provided, it appears that what you're actually wanting to capture contains no spaces, thus we could utilize a negative character class [^\s] or alternatively more precisely [\w.], with either case using a * quantifier.
Your end result would look like "(\d*-[\w.]*)(?=\sLEFT|\sRIGHT|\sUP)"gm. And of course, when . is within the character class it's treated as a literal string - so it's not required to be escaped.
See it live at regex101.com
CodePudding user response:
Try this:
\b\d -[^\r \n] (?= (?:LEFT|RIGHT|UP)\b)
\b\d -[^\r \n]
\bword boundary to ignore things likefoo30-J.RICHARD\dmatch one or more digit.-match a literal-.[^\r \n]match on or more character except\r,\nand a literal space. Excluding\rand\nhelps us not to cross newlines, and that is why\sis not used(i.e., it matches\rand\ntoo)
(?= (?:LEFT|RIGHT|UP)\b) Using positive lookahead.
Ensure there is one or more literal space.(?:LEFT|RIGHT|UP)\busing non-caputring group, ensure our previous spacefollowed by one of these wordsLEFT,RIGHTorUP.\bword boundary to ignore things likeRIGHTfooorLEFTbar.
See regex demo
