\\中的python re regex拆分。 os.linesep用于和不用的空格

时间:2013-12-30 20:59:10

标签: python regex

我希望在句点之后拆分测试,无论该行是否以空格结尾

Test="""
This works.
but this does not because of the whitespace after the period. 

This line not sepearated.
test. don't split here!  
or here
or here
"""

我的尝试在没有空格时分裂

cmds = re.split("(?<=\\.)%s[\t]*"   %    os.linesep, Test, flags=re.M)

我想在两种情况下分开。

2 个答案:

答案 0 :(得分:1)

import re
from pprint import pprint

Test="""
This works.
but this does not because of the whitespace after the period. 

\t     This line not sepearated.
test. don't split here!  
or here
or here  \n    """

r = re.compile('(?<=\.)\s*?^\s*|\s*\Z|\A\s*',re.M)

print '\n'.join(map(repr,Test.splitlines(1)))
print
pprint( r.split(Test) )

结果

'\n'
'This works.\n'
'but this does not because of the whitespace after the period. \n'
'\n'
'\t     This line not sepearated.\n'
"test. don't split here!  \n"
'or here\n'
'or here  \n'
'    '

['',
 'This works.',
 'but this does not because of the whitespace after the period.',
 'This line not sepearated.',
 "test. don't split here!  \nor here\nor here",
 '']

修改

\A^是零长度匹配符号,
它们匹配位于字符串最开头的位置

print [m.start() for m in re.finditer('\A','a\nb\n\nc\n')]
# prints [0]
print [m.start() for m in re.finditer('^', 'a\nb\n\nc\n')]
# prints [0] too

如果在正则表达式的定义中指定了re.MULTILINE标记,则^的表示将扩展到位于换行符\n之后的位置。 这些额外职位由(?<=\n)

匹配
print [m.start() for m in re.finditer('(?<=\n)', 'a\nb\n\nc\n')]
# prints [2, 4, 5, 7]

因此,当在正则表达式中激活re.MULTILINE标记时,^相当于\A|(?<=\n),它匹配字符串的开头和刚刚在换行符之后的所有位置;在显示器上,这些位置被视为所有线条的头部。垂直条|表示OR。

print [m.start() for m in re.finditer('^','a\nb\n\nc\n',re.M)]
print [m.start() for m in re.finditer('\A|(?<=\n)','a\nb\n\nc\n')]
# they print [0, 2, 4, 5, 7]

零长度匹配符号的含义在这个小代码中带有^的证据

print [m.span() for m in re.finditer('^','a\nb\n\nc\n',re.M)]
# prints [(0, 0), (2, 2), (4, 4), (5, 5), (7, 7)]

字符串中有7个字符,表示为'a\nb\n\nc\n'


re.compile('(?<=\.)\s*?^\s*|\s*\Z|\A\s*',re.M)

总模式中有三种部分模式。可以更好地看到这样写:

re.compile('(?<=\.)\s*?^\s*'
           '|'
           '\s*\Z'
           '|'
           '\A\s*',
           re.M)

在我的模式中,(?<=\.)表示在点.之后的强制位置 并且^表示在换行符\n之后强制存在某个职位 正如你所说,它们之间的\s*表示可选的空格 所以(?<=\.)\s*?^表示一连串的空格从一个点开始并在一个换行符之后结束。

*是一个贪婪的量词:这意味着它给正则表达式引擎提供了尽可能多的量化字符的指令。然后,如果正则表达式模式为(?<=\.)\s*^,则与模式中的符号^匹配的位置将是最后一个,尽可能在点之后。
?置于量词之后会消除其贪婪行为。因此(?<=\.)\s*?^表示\s必须匹配尽可能多的空格,然后才会在一条新线之后碰到FIRST位置。 如果您愿意,则相当于'(?<=\.)[ \f\r\t\v]*\n

在该匹配之后,结尾\s*意味着匹配必须继续,直到在点之后的两个位置之间和换行之后的开始匹配之后找到另外的空格。由于\n是由\s表示的空格之一,因此只要没有其他字符作为空格来阻止它,这个结尾\s*就会使引擎电机在所有以下行中前进

因此,每个以点为结尾的句子不可避免地在后续字符中的某个地方被换行符将根据包含该句子后面至少包含换行符的空格的连续进行拆分。

但是对于字符串中的最后一个点,只跟着与\n不同的空格呢? 在这种情况下,这些非换行空格的连续性将不匹配,并且最后一行不会从尾随空格中分离。
为了消除这种痕迹,我将模式\s*\Z作为替代模式,根据该模式进行拆分。因此,直到最后一个非空格字符的最后一行将从此踪迹中分离出来 这是另一种选择,它与第一个部分模式(?<=\.)\s*?^\s*分开,垂直条表示OR。

对于空白的潜在标题也可以这样做:替代模式\A\s*将匹配这样一个潜在的标题,第一行将在字符串的开头正确地从这些空格中剥离。

NOTA BENE

事实上,问号在模式中是不必要的。

(?<=\.)\s*?^\s*
将匹配完全相同的字符串部分 (?<=\.)\s*^\s*
唯一的区别是\s*?匹配所有空格,直到点后第一个换行符之后的位置,
而第二个模式的\s*匹配所有空格,直到最后一个换行后的位置为止。
这没有问题:如果点之后有几个换行符,则表示后面至少有一个换行符,所有这些换行符都用非换行符空格分隔。

顺便说一句,以下模式也适用:
    (?<=\.)\s*\n\s*

以下模式可能是更有效的模式:
    (?<=\.)[ \f\r\t\v]*\n\s*

答案 1 :(得分:0)

如果可以从以空格结尾的行中去除尾部空格,则可以使用以下内容:

re.split(r'(?<=\.)[ \t]*%s' % os.linesep, Test, flags=re.M)