Python 在新行、制表符和一些空格上拆分字符串

Python 在新行、制表符和一些空格上拆分字符串,python,regex,split,Python,Regex,Split,我正在尝试对一组有点不规则的数据执行字符串拆分,这些数据看起来像: \n\tName: John Smith \n\t Home: Anytown USA \n\t Phone: 555-555-555 \n\t Other Home: Somewhere Else \n\t Notes: Other data \n\tName: Jane Smith \n\t Misc: Data with spaces 我想将其转换为tuple/dict,稍后将在冒号上拆分:,但首先我需要去掉

我正在尝试对一组有点不规则的数据执行字符串拆分,这些数据看起来像:

\n\tName: John Smith
\n\t  Home: Anytown USA
\n\t    Phone: 555-555-555
\n\t  Other Home: Somewhere Else
\n\t Notes: Other data
\n\tName: Jane Smith
\n\t  Misc: Data with spaces
我想将其转换为tuple/dict,稍后将在冒号上拆分
,但首先我需要去掉所有多余的空格。我猜正则表达式是最好的方法,但我似乎找不到一个有效的方法,下面是我的尝试

data_string.split('\n\t *')
只需使用,它会在拆分时为您删除所有空白,包括制表符和换行符。然后,可以通过以下方式完成拆分:

输出:

>>> [s.strip() for s in data_string.splitlines()]
['Name: John Smith', 'Home: Anytown USA', 'Phone: 555-555-555', 'Other Home: Somewhere Else', 'Notes: Other data', 'Name: Jane Smith', 'Misc: Data with spaces']
您现在甚至可以在
上内联拆分:

>>> [s.strip().split(': ') for s in data_string.splitlines()]
[['Name', 'John Smith'], ['Home', 'Anytown USA'], ['Phone', '555-555-555'], ['Other Home', 'Somewhere Else'], ['Notes', 'Other data'], ['Name', 'Jane Smith'], ['Misc', 'Data with spaces']]
你可以用这个

string.strip().split(":")

你可以用一块regex石头杀死两只鸟:

>>> r = """
... \n\tName: John Smith
... \n\t  Home: Anytown USA
... \n\t    Phone: 555-555-555
... \n\t  Other Home: Somewhere Else
... \n\t Notes: Other data
... \n\tName: Jane Smith
... \n\t  Misc: Data with spaces
... """
>>> import re
>>> print re.findall(r'(\S[^:]+):\s*(.*\S)', r)
[('Name', 'John Smith'), ('Home', 'Anytown USA'), ('Phone', '555-555-555'), ('Other Home', 'Somewhere Else'), ('Notes', 'Other data'), ('Name', 'Jane Smith'), ('Misc', 'Data with spaces')]
>>> 

正则表达式并不是这项工作的最佳工具。正如其他人所说,结合使用
str.strip()
str.split()。这里有一个简单的例子:

>>> data = '''\n\tName: John Smith
... \n\t  Home: Anytown USA
... \n\t    Phone: 555-555-555
... \n\t  Other Home: Somewhere Else
... \n\t Notes: Other data
... \n\tName: Jane Smith
... \n\t  Misc: Data with spaces'''
>>> {line.strip().split(': ')[0]:line.split(': ')[1] for line in data.splitlines() if line.strip() != ''}
{'Name': 'Jane Smith', 'Other Home': 'Somewhere Else', 'Notes': 'Other data', 'Misc': 'Data with spaces', 'Phone': '555-555-555', 'Home': 'Anytown USA'}
如果您查看str.split的

如果未指定sep或sep为None,则应用不同的拆分算法:连续空格的运行被视为单个分隔符,如果字符串具有前导或尾随空格,则结果的开头或结尾将不包含空字符串。因此,拆分空字符串或仅包含空格且带有None分隔符的字符串将返回[]

换句话说,如果您正试图找出要传递到
split
以获得
'\n\t名称:Jane Smith'
['Name:','Jane','Smith']
,只需不传递任何内容(或不传递任何内容)

这几乎解决了你的整个问题。剩下两部分

首先,您只有两个字段,第二个字段可以包含空格。所以,你只需要一次分割,而不是尽可能多的分割。因此:

s.split(None, 1)
接下来,你还有那些讨厌的冒号。但你不需要对他们分道扬镳。至少根据您向我们展示的数据,冒号总是出现在第一个字段的末尾,前面没有空格,后面总是空格,因此您可以删除它:

key, value = s.split(None, 1)
key = key[:-1]

当然,还有一百万种其他方法可以做到这一点;这似乎与您已经尝试过的最接近。

非常好,但您的
[\t]*
没有任何作用;
(.+)
将始终使用尾随空格(如果有)。您可以这样做:
(.+?)[\t]*$
。不情愿的量词允许它提前停止,而
$
确保它仍然占用整行。这非常有效,的语法不是我以前见过的,所以我想我必须仔细阅读它。
s.split(None, 1)
key, value = s.split(None, 1)
key = key[:-1]