2016-05-13 44 views
0

我有这样分割空间但如果有一个冒号后面的空间或如果在引号中的空间

str = 'name: phil age : 23 range: 33, 45 address: "main ave US"' 

一个字符串被标记化作为

['name: phil', 'age : 23', 'range: 33, 45' 'address: "main ave US"'] 
+0

这不是纯粹的正则表达式操作。你在用什么语言?此外,这些数据的来源是什么?它几乎看起来像JSON,如果是的话,你只需要使用JSON解析器。 –

+0

您的预期输出甚至不符合您的描述。这是**而不是**正则表达式的意义。你应该使用专用的词法分析器/解析器。 – Amit

+0

它不是JSON。源是输入框中输入的原始字符串。 – rdp

回答

2

样品字符串1

>>> import re 
>>> str = 'name: phil age : 23 range: 33, 45 address: "main ave US"' 
>>> re.findall(r'\w+\s*:\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))', str) 
['name: phil ', 'age : 23 ', 'range: 33, 45 ', 'address: "main ave US"'] 

样本串2

>>> str = 'name: phil age : 23 range: 33, 45 address: "main ave US" abcd : xyz' 
>>> re.findall(r'\w+\s*:\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))', str) 
['name: phil ', 'age : 23 ', 'range: 33, 45 ', 'address: "main ave US"', 'abcd : xyz'] 

样品串3

>>> str = 'name: phil age : 23 range: 33, 45' 
>>> re.findall(r'\w+\s*:\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))', str) 
['name: phil ', 'age : 23 ', 'range: 33, 45'] 

要修剪的领导和各的尾随空格匹配您可以使用此:

>>> list(map(lambda x:x.strip(), re.findall(r'\w+\s*:\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))', str))) 
['name: phil', 'age : 23', 'range: 33, 45'] 

正则表达式使用的是:\w+\s*:\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))


边缘的情况下:

>>> str='word1 word2 name: phil age : 23 range: 33, 45' 
>>> list(map(lambda x:x.strip() if ':' in x else list(map(lambda s:s.strip(), x.split())), re.findall(r'\w+\s*:?\s*(?:"[^"]*"|.*?(?=\w+\s*:\s*|$))?' , str))) 
[['word1', 'word2'], 'name: phil', 'age : 23', 'range: 33, 45'] 

一旦你有了上述结构,你可以使用给出here

+0

我会接受这个答案,但正如你所提到的,它并不适用于所有情况,例如str ='name:phil age:23 range:33,45' 感谢您的努力 – rdp

+0

@dilip编辑了ans与例子和一个新的正则表达式..现在看看 – ritesht93

+0

完美。这工作。谢谢。如果可能的话,你还可以看看一个角落案例str ='word1 word2 name:phil age:23 range:33,45'=> ['word1','word2','name:phil','age:23', '范围:33,45']。但是你按照这个问题回答,我接受了。辉煌的工作。如果你能处理上面的边缘情况,也会很高兴。 – rdp

1

此正则表达式的答案中的任意1应该是相当稳定的扁平化列表。它仅检查密钥名称后面跟一个冒号,并将它们视为匹配的开始和未包含的结束,使用积极的前瞻。

根据您要如何进一步处理它,您可以使用简单的变体:

\w+\s*:.*?(?=(?:\w+\s*:)|$) 

这将匹配整个键/值对,包括所有的空格。

Check this regex out on regex101.com


如果你要在结肠反正最多分裂对,例如将它们存储在字典中,你还可使用此略作修改正则表达式,它返回一个元组(key, value)对于每一对,与开头和结尾已经剥离空间:

(\w+)\s*:\s*(.*?)\s*(?=(?:\w+\s*:)|$) 

Check this regex out on regex101.com


这里有一个Python的例子如何使用这两个正则表达式:

import re 

pattern1 = r'\w+\s*:.*?(?=(?:\w+\s*:)|$)' 
pattern2 = r'(\w+)\s*:\s*(.*?)\s*(?=(?:\w+\s*:)|$)' 
data = 'name: phil age : 23 range: 33, 45 address: "main ave US"' 

print('Pattern 1:', re.findall(pattern1, data)) 
print('Pattern 2:', re.findall(pattern2, data)) 

输出:

Pattern 1: ['name: phil ', 'age : 23 ', 'range: 33, 45 ', 'address: "main ave US"'] 
Pattern 2: [('name', 'phil'), ('age', '23'), ('range', '33, 45'), ('address', '"main ave US"')] 

See this code running on ideone.com