次のことを試してください。
re.findall(r'^(\w+):(.*?)(?=^\w+:|\Z)', text, flags=re.DOTALL | re.MULTILINE)
例:
>>> text = '''rootvg:
... hd5 boot 1 1 1 closed/syncd N/A
... hd4 jfs 38 38 1 open/syncd /
... datavg:
... data01lv jfs 7 7 1 open/syncd /data1
... data02lv jfs 7 7 1 open/syncd /data2'''
>>> re.findall(r'^(\w+):(.*?)(?=^\w+:|\Z)', text, flags=re.DOTALL | re.MULTILINE)
[('rootvg', '\nhd5 boot 1 1 1 closed/syncd N/A\nhd4 jfs 38 38 1 open/syncd /\n'), ('datavg', '\ndata01lv jfs 7 7 1 open/syncd /data1\ndata02lv jfs 7 7 1 open/syncd /data2')]
re.DOTALL
フラグは改行.
文字と一致できるようにし、フラグre.MULTILINE
は文字列の先頭と末尾だけでなく、それぞれ行頭と行末で一致できるようにします。^
$
説明:
^ # match at the start of a line
(\w+) # match one or more letters or numbers and capture in group 1
: # match a literal ':'
(.*?) # match zero or more characters, as few as possible
(?= # start lookahead (only match if following regex can match)
^\w+: # start of line followed by word characters then ':'
| # OR
\Z # end of the string
) # end lookahead
または、より単純な正規表現を使用re.split()
して同様の出力を取得することもできます。これを必要な形式に変換するのはそれほど難しくありません。
>>> re.split(r'^(\w+):', text, flags=re.MULTILINE)
['', 'rootvg', '\nhd5 boot 1 1 1 closed/syncd N/A\nhd4 jfs 38 38 1 open/syncd /\n', 'datavg', '\ndata01lv jfs 7 7 1 open/syncd /data1\ndata02lv jfs 7 7 1 open/syncd /data2']
これを目的の形式に変換する方法は次のとおりです。
>>> matches = re.split(r'^(\w+):', text, flags=re.MULTILINE)
>>> [(v, matches[i+1]) for i, v in enumerate(matches) if i % 2]
[('rootvg', '\nhd5 boot 1 1 1 closed/syncd N/A\nhd4 jfs 38 38 1 open/syncd /\n'), ('datavg', '\ndata01lv jfs 7 7 1 open/syncd /data1\ndata02lv jfs 7 7 1 open/syncd /data2')]