How to only use input in pattern once?

Viewed 35

regex = ^(movie|tv) (.*) (?<=season )([0-9 ]+)

input = tv game of thrones season 1 2 3

output

tv
game of thrones season
1 2 3

desired output

tv
game of thrones
1 2 3

https://regex101.com/r/wG3aM3/954

(.*) captures all string before ([0-9 ]+) how can i prevent it from capturing (?<=season ) which is before ([0-9 ]+).

P.S i cant just negate "season" from (.*) . i.e tv game of season season 1 2 3 should capture tv game of season 1 2 3

2 Answers

You can use

^(movie|tv)\s*(.*?)(?:\s+season)?(?:\s+([0-9]+(?:\s+[0-9]+)*))?$

See the regex demo.

Details

  • ^ - start of string
  • (movie|tv) - Group 1: movie or tv
  • \s* - zero or more whitespaces
  • (.*?) - Group 2: any zero or more chars other than line break chars as few as possible
  • (?:\s+season)? - an optional non-capturing group matching one or more whitespaces followed with season string
  • (?:\s+([0-9]+(?:\s+[0-9]+)*))? - an optional non-capturing group matching
    • \s+ - one or more whitespaces
    • ([0-9]+(?:\s+[0-9]+)*) - Group 3: one or more digits followed with zero or more repetitions of one or more whitespace chars followed with one or more digits
  • $ - end of string.

What about this?

^(movie|tv) (.*) (?:season )([0-9 ]+)

This just changes the lookahead (?<=season ) to a non-capturing group (?:season ). In python that would be:

import re
text = "tv game of thrones season 1 2 3"
output = re.findall(r"^(movie|tv) (.*) (?:season )([0-9 ]+)", text)
print(output)
#output: [('tv', 'game of thrones', '1 2 3')]

A non-capturing version of regular parentheses. Matches whatever regular expression is inside the parentheses, but the substring matched by the group cannot be retrieved after performing a match or referenced later in the pattern.

see https://docs.python.org/3/library/re.html

Related