我得到了这个正则表达式:
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']
编辑 1
在 Cartroo 的评论之后,一个更准确的新正则表达式:
import re
pat = ('(?<!\S)' # absence of non-whitespace before
'(?:'
'[^\s<>]+'
'|' # OR
'(?:[^\s<>]*)'
'(?:'
'<'
'[^<>]*?'
'(?:<[^<>]*?>[^<>]*)*'
'[^<>]*?'
'>'
')'
'(?:[^\s<>]*)'
')'
'(?!\S)' # absence of non-whitespace after)
)
reg = re.compile(pat)
ss = ("spam i>j bar ds<hai bye>sd baz eggs Z<boo <abv>"
" foo>W ttt <two<;>*<:> three> ")
print '%s\n' % ss
print reg.findall(ss)
ss = "a<b<E1>c>d <b<E2>c>d <b<E3>c> a<<E4>c>d <<E5>>d
<<E6>> <<>>"
print '\n\n%s\n' % ss
print reg.findall(ss)
结果
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>>', '<<>>']
上述字符串形成良好,结果一致。
在格式不正确的文本上(关于括号),它可能会给出非预期的结果:
ss = """A<B<C>D
E<F<G>H
I<J>K>
L<<M>N
O<P>>Q
R<<S> T<<>"""
print '\n\n%s\n' % ss
print reg.findall(ss)
结果
A<B<C>D
E<F<G>H
I<J>K>
L<<M>N
O<P>>Q
R<<S> T<<>
['E<F<G>H \nI<J>K>', 'L<<M>N\n O<P>>Q']
那是因为末尾的星号'(?:<[^<>]*?>[^<>]*)*'
。可以通过移除星号来关闭此行为。这种行为使得难以使用正则表达式来分析这种“复杂”的文本,正如 Crtaroo 所称的那样。
.
编辑 2
当我说结果是不想要的结果时'E<F<G>H \nI<J>K>'
,'L<<M>N\n O<P>>Q'
这并不意味着找到的匹配部分不尊重正则表达式的模式(怎么可能?),因为我制作了它;匹配部分形成良好,确实:
两个部分<G>
,<J>
位于两个支架之间< <G> <J> >
两个部分<M>
,<P>
位于两个支架之间< <M> <P> >
事实上,这是一种轻描淡写的说法,意味着找到的每个匹配部分都应该只延伸一行。但是,一旦轻描淡写地表达出来,就会出现一个可能的解决方案。
如果不需要在多行上延伸的匹配部分,很容易告诉正则表达式不匹配它们,这与我写的相反。\n
在正则表达式模式的某些地方添加字符就足够了。
事实上,这意味着匹配部分不能越过一个\n
字符,然后这个字符可以被认为是匹配部分的分隔符。因此,可能需要任何其他字符作为同一行上存在的匹配部分之间的分隔符,例如#
在以下代码中。
.
正则表达式不能做饭或从学校接孩子,但它们非常强大。说正则表达式对格式错误的文本的行为是一个问题太短了:必须补充说这是文本的问题,而不是正则表达式。一个正则表达式做它被命令做的事情:吃掉给它的任何文本。它贪婪地吃掉它,也就是说,在没有验证任何一致性的情况下,这不是它的预期行为,如果它被喂食了不合饮食的文字,它是不负责任的。说正则表达式在格式错误的文本上的行为是一个问题,听起来好像有人会责备孩子有时会用威士忌和胡椒食品来滋养。
编码员有责任确保传递给正则表达式的文本格式正确。就像编码人员将验证片段放入代码中以确保条目是整数以便程序正确运行一样。
.
这一点与试图将标记文本解析为 XML 文本时滥用正则表达式不同。正则表达式无法解析这样的文本,好吧,因为不可能制作出能够对格式错误的标记文本做出正确反应的正则表达式。不尝试这样做也是编码人员的责任。这并不意味着如果该文本已经过验证,则
不得使用正则表达式来分析标记文本。
无论如何,如果文本格式错误太多,即使解析器也不会捕获数据。
我的意思是我们必须区分:
.
import re
ss = """
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<<>"""
print '%s\n' % ss
pat = ('(?<!\S)' # absence of non-whitespace before
'(?:[^\s<>]*)'
'(?:<'
'[^<>]*?'
'(?:<[^<>]*?>[^<>]*)*'
'>)'
'(?:[^\s<>]*)'
'(?!\S)' # absence of non-whitespace after)
)
reg = re.compile(pat)
print '------------------------------'
print '\n'.join(map(repr,reg.findall(ss)))
pat = ('(?<!\S)' # absence of non-whitespace before
'(?:[^\s<>]*)'
'(?:<'
'[^<>\n]*?'
'(?:<[^<>\n]*?>[^<>\n]*)*'
'>)'
'(?:[^\s<>]*)'
'(?!\S)' # absence of non-whitespace after)
)
reg = re.compile(pat)
print '\n----------- with \\n -------------'
print '\n'.join(map(repr,reg.findall(ss)))
pat = ('(?<!\S)' # absence of non-whitespace before
'(?:[^\s<>]*)'
'(?:<'
'[^<>#]*?'
'(?:<[^<>#]*?>[^<>#]*)*'
'>)'
'(?:[^\s<>]*)'
'(?!\S)' # absence of non-whitespace after)
)
reg = re.compile(pat)
print '\n------------- with # -----------'
print '\n'.join(map(repr,reg.findall(ss)))
pat = ('(?<!\S)' # absence of non-whitespace before
'(?:[^\s<>#]*)'
'(?:<'
'[^<>#]*?'
'(?:<[^<>#]*?>[^<>#]*)*'
'>)'
'(?:[^\s<>]*)'
'(?!\S)' # absence of non-whitespace after)
)
reg = re.compile(pat)
print '\n------ with ^# everywhere -------'
print '\n'.join(map(repr,reg.findall(ss)))
结果
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'