splitやre.splitよりshelex.split使うとよい場合が多い
shelex.splitはデフォルトでPOSIXモードで動作するので引用符(‘)、二重引用符(“)で囲まれた文字列をいい感じに判断してくれる。
ちなみに、shlex.splitはデフォルトでは空白文字(\s. \t. \r, \n, \r\n)をdelimita(区切り文字)と判定している。と思う
>>> import re, shlex, textwrap
>>> from rich import pretty, print
>>> pretty.install()
>>>
>>> test_orig_text = textwrap.dedent('''\
... 1.0.0.1 None None None
... 8.8.4.4 None None None
... 198.51.100.0 None None None
... a b c d
... a b this is a this
... s m sm "hoge hoge"
... a,b,c,d
... ''')
>>>
>>> test_re_text = []
>>> test_shlex_text = []
>>>
>>> for l in test_orig_text.splitlines():
... test_re_text.append(re.findall(r'\S+', l))
... test_shlex_text.append(shlex.split(l))
...
>>> print(test_re_text)
[
['1.0.0.1', 'None', 'None', 'None'],
['8.8.4.4', 'None', 'None', 'None'],
['198.51.100.0', 'None', 'None', 'None'],
['a', 'b', 'c', 'd'],
['a', 'b', 'this', 'is', 'a', 'this'],
['s', 'm', 'sm', '"hoge', 'hoge"'],
['a,b,c,d']
]
>>> print(test_shlex_text)
[
['1.0.0.1', 'None', 'None', 'None'],
['8.8.4.4', 'None', 'None', 'None'],
['198.51.100.0', 'None', 'None', 'None'],
['a', 'b', 'c', 'd'],
['a', 'b', 'this', 'is', 'a', 'this'],
['s', 'm', 'sm', 'hoge hoge'],
['a,b,c,d']
]
>>>
>>> print(shlex.split(test_orig_text))
['1.0.0.1', 'None', 'None', 'None', '8.8.4.4', 'None', 'None', 'None', '198.51.100.0', 'None', 'None', 'None', 'a', 'b', 'c', 'd', 'a', 'b', 'this', 'is', 'a', 'this', 's', 'm', 'sm', 'hoge hoge', 'a,b,c,d']
>>>
shelexでカンマ区切りしたい場合。
余分なスペースもいい感じに排除してくれる。
>>> import shlex, textwrap
>>>
>>> test_orig_text = textwrap.dedent('''\
... 1.0.0.1 None None None
... 8.8.4.4 None None None
... 198.51.100.0 None None None
... a b c d
... a b this is a this
... s m sm "hoge hoge"
... a,b,c,d
... a , b, c , d
... ''')
>>>
>>>
>>> test_shlex_shlex = shlex.shlex(test_orig_text)
>>> test_shlex_shlex.whitespace += ','
>>> test_shlex_shlex.whitespace_split = True
>>> print(list(test_shlex_shlex))
['1.0.0.1', 'None', 'None', 'None', '8.8.4.4', 'None', 'None', 'None', '198.51.100.0', 'None', 'None', 'None', 'a', 'b', 'c', 'd', 'a', 'b', 'this', 'is', 'a', 'this', 's', 'm', 'sm', '"hoge hoge"', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd']
>>>
さらにちなみに、正規表現の変態になるとこんなことになるらしい。(カンマ区切りの例だけど)
>>> import re
>>> pattern = re.compile(r'\s*("[^"]*"|.*?)\s*,')
>>> def split(line):
... return [x[1:-1] if x[:1] == x[-1:] == '"' else x
... for x in pattern.findall(line.rstrip(',') + ',')]
...
>>> split("foo, bar, baz")
['foo', 'bar', 'baz']
>>> split('foo, bar, baz, "blub blah"')
['foo', 'bar', 'baz', 'blub blah']