Reputation: 6223
I have the following text:
Test 123:
This is a blue car
Test:
This car is not blue
This car is yellow
Hello:
This is not a test
I want to put together a regex that finds all items that start with a Test
or a Hello
and precede a colon, and optionally a tree digit number, and return all content after that until the next line that fits that same description. So for above text, the findall regex would return an array of:
[("Test", "123", "\nThis is a blue car\n"),
("Test", "", "\nThis car is not blue\n\nThis car is yellow\n"),
("Hello", "", "\nThis is not a test")]
So far I got this:
r = re.findall(r'^(Test|Hello) *([^:]*):$', test, re.MULTILINE)
It matches each line according to the description but I'm unsure how to capture the content until the next line that ends with a colon. Any ideas?
Upvotes: 3
Views: 3883
Reputation: 67978
import re
p = re.compile(ur'(Test|Hello)\s*([^:]*):\n(\n.*?)(?=Test[^:]*:|Hello[^:]*:|$)', re.DOTALL | re.IGNORECASE)
test_str = u"Test 123:\n\nThis is a blue car\n\nTest:\n\nThis car is not blue\n\nThis car is yellow\n\nHello:\n\nThis is not a test"
re.findall(p, test_str)
You can try this.See demo.
http://regex101.com/r/eM1xP0/1
Upvotes: 0
Reputation: 174786
You could use the below regex which uses DOTALL modifier,
(?:^|\n)(Test|Hello) *([^:]*):\n(.*?)(?=\n(?:Test|Hello)|$)
>>> import re
>>> s = """Test 123:
...
... This is a blue car
...
... Test:
...
... This car is not blue
...
... This car is yellow
...
... Hello:
...
... This is not a test"""
>>> re.findall(r'(?s)(?:^|\n)(Test|Hello) *([^:]*):\n(.*?)(?=\n(?:Test|Hello)|$)', s)
[('Test', '123', '\nThis is a blue car\n'), ('Test', '', '\nThis car is not blue\n\nThis car is yellow\n'), ('Hello', '', '\nThis is not a test')]
Upvotes: 5