You can make use of re.split to split into sections and then look for the [failed] string in the each section:
splitted = re.split(r'(\d{1,2})\.(.*)(?= _{3,})', text)
failed = [(splitted[i-2], splitted[i-1]) for i, s in enumerate(splitted) if re.search(r'\[failed\]', s)]
failed
# [('9', 'TX_MULTI_VERIFICATION 2412 DSSS-1 NON_HT BW-20 TX1'), 
#  ('11', 'TX_MULTI_VERIFICATION 2472 DSSS-1 NON_HT BW-20 TX1'), 
#  ('12', 'TX_MULTI_VERIFICATION 2412 CCK-11 NON_HT BW-20 TX1')]
Here the re.split split the text into three sub groups:
 1. Group 1 (the section number)
 2. Group 2 (the section title)
 3. Group 3 (the section body)
If there is a match in Group 3, you refer back to Group 1 and 2 – hence, splitted[i-2] and splitted[i-1])
solved Regular expression doesn’t produce expected result