Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中使用regexp进行标记化_Python_Regex_Parsing_Token_Tokenize - Fatal编程技术网

在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表达的需求,而是为了好玩,他在回答中说:“这种方法的问题是,如果你期望嵌套的尖括号,那么你就得不到你所期望的(…)我认为这是正则表达式无法解决的问题,你需要一些东西