在Python中使用regexp进行标记化
我尝试将一个字符串标记为在Python中使用regexp进行标记化,python,regex,parsing,token,tokenize,Python,Regex,Parsing,Token,Tokenize,我尝试将一个字符串标记为“spam bar dssd baz eggs”到一个列表中['spam'、'bar'、'dssd'、'baz'、'eggs'],例如str.split(),但在中保留空格 我的解决方案是使用re.split和(\S*\S*)\S+模式。然而,我得到以下信息: >>> re.split('(\S*<.*?>\S*)|\s+', "spam bar ds<hai bye>sd baz eggs") ['spam', None, 'b
“spam bar dssd baz eggs”
到一个列表中['spam'、'bar'、'dssd'、'baz'、'eggs']
,例如str.split()
,但在中保留空格代码>
我的解决方案是使用re.split
和(\S*\S*)\S+
模式。然而,我得到以下信息:
>>> re.split('(\S*<.*?>\S*)|\s+', "spam bar ds<hai bye>sd baz eggs")
['spam', None, 'bar', None, '', 'ds<hai bye>sd', '', None, 'baz', None, 'eggs']
>>re.split(“(\S*\S*)|\S+”,“垃圾邮件栏dssd baz鸡蛋”)
['spam',None',bar',None','dssd','',None',baz',None',egons']
不确定那些None
s和空字符串来自何处。一、 当然,我可以用列表来过滤掉它们,如果是s,那么结果是s,但是在我知道原因之前,我不愿意这样做
所以,(1)为什么那些None
s和空字符串,(2)它能做得更好吗?这些None
和空字符串值是因为您在模式中使用了捕获括号,所以拆分包括匹配的文本-有关这一点,请参阅
如果您将模式修改为r”((?:\S*\S*)|\S+)
(即,转义括号以使其不捕获,并将空白更正为非空白),则应该可以工作,但只能保留分隔符,然后需要通过跳过替代项来过滤掉分隔符。我认为你最好这样做:
ITEM_RE = re.compile(r"(?:\S*<.*?>\S*)|\S+")
ITEM_RE.findall("spam bar ds<hai bye>sd baz eggs")
ITEM_RE=RE.compile(r“(?:\S*\S*)|\S+”)
关于findall的项目(“垃圾邮件栏dssd baz鸡蛋”)
如果您不需要实际列表(即一次只浏览一项),则finditer()
更有效,因为它一次只生成一个列表。如果你很可能在不看全部清单的情况下摆脱困境,这一点尤其正确
从原则上讲,消极的后视断言也是可能的,但实际上,我认为创建一个足够灵活的后视断言是不可能的——我尝试了r“(?]*)\s+”
,得到了错误“后视需要固定宽度模式”,所以我想这是不可能的。文档证实了这种后视断言(正片和负片)都需要固定宽度
这种方法的问题是,如果您希望使用嵌套的尖括号,那么您将得不到您所期望的。例如,解析dssd
将产生ds,None
和空字符串值是因为您在模式中使用了捕获括号,因此分割包含匹配的文本-请参阅f或者提到这个
如果您将模式修改为r”((?:\S*\S*)|\S+)
(即,转义括号以使其不捕获,并将空白更正为非空白),则应该可以工作,但只需保留分隔符,然后需要通过跳过替代项来过滤掉分隔符。我认为您最好这样做:
ITEM_RE = re.compile(r"(?:\S*<.*?>\S*)|\S+")
ITEM_RE.findall("spam bar ds<hai bye>sd baz eggs")
ITEM_RE=RE.compile(r“(?:\S*\S*)|\S+”)
关于findall的项目(“垃圾邮件栏dssd baz鸡蛋”)
如果您不需要实际的列表(即一次只查看一项),则finditer()
更有效,因为它一次只生成一个列表。如果您可能在不查看整个列表的情况下退出,尤其如此
从原则上讲,消极的后视断言也是可能的,但实际上,我认为创建一个足够灵活的后视断言是不可能的——我尝试了r“(?]*)\s+”
,得到了错误“后视需要固定宽度模式”,所以我想这是不可能的。文档证实了这种后视断言(正片和负片)都需要固定宽度
这种方法的问题是,如果您希望使用嵌套的尖括号,那么您将得不到您所期望的。例如,解析dssd
将产生ds我相信无
值是由于模式中存在()
s,基于文档中的这一行:
如果模式中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回
在您的输入上使用还可以帮助可视化解析:http://regexpal.com/?flags=g®ex=%28\S*%3C.*%3F%3E\S*%29 |\S%2B&input=spam%20bar%20ds%3Chai%20bye%3Esd%20baz%20egs我相信无
值是由于模式中存在()
S,基于文档中的这一行:
如果模式中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回
在您的输入上使用还可以帮助可视化解析:http://regexpal.com/?flags=g®ex=%28\S*%3C.*%3F%3E\S*%29 |\S%2B&input=spam%20bar%20ds%3Chai%20bye%3Esd%20baz%20eggs
ss = "spam bar ds<hai bye>sd baz eggs ZQ<boo <abv> foo>WX "
reg = re.compile('(?:'
'\S*?'
'<'
'[^<>]*?'
'(?:<[^<>]*>[^<>]*)*'
'[^<>]*?'
'>'
')?'
'\S+')
print reg.findall(ss)
结果
['spam', 'bar', 'ds<hai bye>sd', 'baz', 'eggs',
'ZQ<boo <abv> foo>WX']
spam i>j bar ds<hai bye>sd baz eggs Z<boo <abv> foo>W
ttt <two<;>*<:> three>
['spam', 'bar', 'ds<hai bye>sd', 'baz', 'eggs',
'Z<boo <abv> foo>W', 'ttt', '<two<;>*<:> three>']
a<b<E1>c>d <b<E2>c>d <b<E3>c> a<<E4>c>d <<E5>>d <<E6>> <<>>
['a<b<E1>c>d', '<b<E2>c>d', '<b<E3>c>', 'a<<E4>c>d', '<<E5>>d',
'<<E6>>', '<<>>']
A<:<11>:<12>:>
fgh
A<#:<33>:<34>:>
A#<:<55>:<56>:>
A<:<77>:<78> i<j>
A<B<C>D #
E<F<G>H #
I<J>K>
L<<M>N
O<P>>Q #
R<<S> T<<>
------------------------------
'A<:<11>:<12>:>'
'A<#:<33>:<34>:>'
'A#<:<55>:<56>:>'
'i<j>'
'E<F<G>H #\n I<J>K>'
'L<<M>N \n O<P>>Q'
----------- with \n -------------
'A<:<11>:<12>:>'
'A<#:<33>:<34>:>'
'A#<:<55>:<56>:>'
'i<j>'
------------- with # -----------
'A<:<11>:<12>:>'
'A#<:<55>:<56>:>'
'i<j>'
'L<<M>N \n O<P>>Q'
------ with ^# everywhere -------
'A<:<11>:<12>:>'
'i<j>'
'L<<M>N \n O<P>>Q'
A
fgh
A.
A#
A我得到了这个正则表达式:
ss = "spam bar ds<hai bye>sd baz eggs ZQ<boo <abv> foo>WX "
reg = re.compile('(?:'
'\S*?'
'<'
'[^<>]*?'
'(?:<[^<>]*>[^<>]*)*'
'[^<>]*?'
'>'
')?'
'\S+')
print reg.findall(ss)
结果
['spam', 'bar', 'ds<hai bye>sd', 'baz', 'eggs',
'ZQ<boo <abv> foo>WX']
spam i>j bar ds<hai bye>sd baz eggs Z<boo <abv> foo>W
ttt <two<;>*<:> three>
['spam', 'bar', 'ds<hai bye>sd', 'baz', 'eggs',
'Z<boo <abv> foo>W', 'ttt', '<two<;>*<:> three>']
a<b<E1>c>d <b<E2>c>d <b<E3>c> a<<E4>c>d <<E5>>d <<E6>> <<>>
['a<b<E1>c>d', '<b<E2>c>d', '<b<E3>c>', 'a<<E4>c>d', '<<E5>>d',
'<<E6>>', '<<>>']
A<:<11>:<12>:>
fgh
A<#:<33>:<34>:>
A#<:<55>:<56>:>
A<:<77>:<78> i<j>
A<B<C>D #
E<F<G>H #
I<J>K>
L<<M>N
O<P>>Q #
R<<S> T<<>
------------------------------
'A<:<11>:<12>:>'
'A<#:<33>:<34>:>'
'A#<:<55>:<56>:>'
'i<j>'
'E<F<G>H #\n I<J>K>'
'L<<M>N \n O<P>>Q'
----------- with \n -------------
'A<:<11>:<12>:>'
'A<#:<33>:<34>:>'
'A#<:<55>:<56>:>'
'i<j>'
------------- with # -----------
'A<:<11>:<12>:>'
'A#<:<55>:<56>:>'
'i<j>'
'L<<M>N \n O<P>>Q'
------ with ^# everywhere -------
'A<:<11>:<12>:>'
'i<j>'
'L<<M>N \n O<P>>Q'
A
fgh
A.
A#
A除非此模式要求至少有一个字符位于尖括号之外。例如,在“一四”
上尝试此模式,但它不会达到您预期的效果。您可以通过将最后的\S+
更改为\S*
并添加额外的替代项来覆盖\S+
案例(即没有尖括号)来解决此问题-这是因为如果有尖括号,那么实际上不需要任何其他字符使其成为有效标记(我假设)。但是,我还没有测试过。不管怎样,这是卷积,它表明正则表达式不是这里的最佳解决方案。+1对于第二个正则表达式,但为什么要尝试容纳嵌套的括号?我在问题或任何评论中都看不到这一要求。@Alanmore这并不是为了回答OP表达的需求,而是为了好玩,他在回答中说:“这种方法的问题是,如果你期望嵌套的尖括号,那么你就得不到你所期望的(…)我认为这是正则表达式无法解决的问题,你需要一些东西