正则表达式 - 除非是尊敬的一部分,否则将全部分裂

时间:2016-08-08 14:09:30

标签: python regex string python-2.7

我有一个包含所有可能标题的列表:

['Mr.', 'Mrs.', 'Ms.', 'Dr.', 'Prof.', 'Rev.', 'Capt.', 'Lt.-Col.', 'Col.', 'Lt.-Cmdr.', 'The Hon.', 'Cmdr.', 'Flt. Lt.', 'Brgdr.', 'Wng. Cmdr.', 'Group Capt.' ,'Rt.', 'Maj.-Gen.', 'Rear Admrl.', 'Esq.', 'Mx', 'Adv', 'Jr.']

我需要一个Python 2.7代码,可以用换行符\.替换所有句号\n,除非它是上述标题之一。

将它拆分成字符串列表也没关系。

示例输入:

Modi is waiting in line to Thank Dr. Manmohan Singh for preparing a road map for introduction of GST in India. The bill is set to pass.

样本输出:

Modi is waiting in line to Thank Dr. Manmohan Singh for preparing a road map for introduction of GST in India. The bill is set to pass.

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题,在这里我们使用列表理解条件语句,如果它们包含一个完整的单词,则将这些单词与\n连接起来。停止,并且不在关键词列表中。否则只是连接一个空格。

最后,句子中的单词使用join()加入,我们使用rstrip()来消除字符串末尾剩余的换行符。

l = set(['Mr.', 'Mrs.', 'Ms.', 'Dr.', 'Prof.', 'Rev.', 'Capt.', 'Lt.-Col.', 
'Col.', 'Lt.-Cmdr.', 'The Hon.', 'Cmdr.', 'Flt. Lt.', 'Brgdr.', 'Wng. Cmdr.', 
'Group Capt.' ,'Rt.', 'Maj.-Gen.', 'Rear Admrl.', 'Esq.', 'Mx', 'Adv', 'Jr.'] )
s = 'Modi is waiting in line to Thank Dr. Manmohan Singh for preparing a road 
map for introduction of GST in India. The bill is set to pass.'

def split_at_period(input_str, keywords):
     final = []
     split_l = input_str.split(' ')

    for word in split_l:
        if '.' in word and word not in keywords:
            final.append(word + '\n')
            continue
        final.append(word + ' ')

    return ''.join(final).rstrip()

print split_at_period(s, l)

一个班轮:D

print ''.join([w + '\n' if '.' in w and w not in l else w + ' ' for w in s.split(' ')]).rstrip()

示例输出:

Modi is waiting in line to Thank Dr. Manmohan Singh for preparing a road map for introduction of GST in India.
The bill is set to pass.

如何运作?

首先,我们使用' '字符串函数将字符串与空格split()分隔符分开,从而返回以下list

>>> ['Modi', 'is', 'waiting', 'in', 'line', 'to', 'Thank', 'Dr.', 
'Manmohan', 'Singh', 'for', 'preparing', 'a', 'road', 'map', 'for', 
'introduction', 'of', 'GST', 'in', 'India.', 'The', 'bill', 'is', 
'set', 'to', 'pass.']

然后,我们通过迭代拆分列表开始构建新列表。如果我们看到word包含句点,但不是关键字,( Ex: India. pass. 在这种情况下)然后我们必须将换行符 \n连接到开始新单词。然后,我们可以append()到我们的final列表,并从当前迭代中continue

如果单词没有以句点结尾,我们可以连接一个空格来重建原始字符串。

这是final在使用join()构建为字符串之前的样子。

>>> ['Modi ', 'is ', 'waiting ', 'in ', 'line ', 'to ', 'Thank ', 'Dr. 
', 'Manmohan ', 'Singh ', 'for ', 'preparing ', 'a ', 'road ', 'map ', 
'for ', 'introduction ', 'of ', 'GST ', 'in ', 'India.\n', 'The ', 'bill ', 
'is ', 'set ', 'to ', 'pass.\n']

很好,我们有空格换行符他们需要的地方!现在,我们可以重建字符串。注意但是,列表中的最后一个元素也恰好包含\n,我们可以在新字符串上调用rstrip()来清理它。

初始解决方案不支持关键字中的空格,我在下面提供了一个新的更强大的解决方案:

import re

def format_string(input_string, keywords):
    regexes = '|'.join(keywords)  # Combine all keywords into a regex.
    split_list = re.split(regexes, input_string)  # Split on keys.
    removed = re.findall(regexes, input_string)  # Find removed keys.
    newly_joined = split_list + removed  # Interleave removed and split.
    newly_joined[::2] = split_list
    newly_joined[1::2] = removed
    space_regex = '\.\s*'

    for index, section in enumerate(newly_joined):
        if '.' in section and section not in removed:
            newly_joined[index] = re.sub(space_regex, '.\n', section)
    return ''.join(newly_joined).strip()

答案 1 :(得分:0)

  • 将所有标题(和唯一的点)转换为正则表达式
  • 使用替换回拨

代码:

import re

l = "|".join(map(re.escape,['.','Mr.', 'Mrs.', 'Ms.', 'Dr.', 'Prof.', 'Rev.', 'Capt.', 'Lt.-Col.', 'Col.', 'Lt.-Cmdr.', 'The Hon.', 'Cmdr.', 'Flt. Lt.', 'Brgdr.', 'Wng. Cmdr.', 'Group Capt.' ,'Rt.', 'Maj.-Gen.', 'Rear Admrl.', 'Esq.', 'Mx', 'Adv', 'Jr.']))

e="Dear Mr. Foo, I would like to thank you. Because Lt.-Col. Collins told me blah blah. Bye."

def do_repl(m):
    s = m.group(1)
    if s==".":
        rval=".\n"
    else:
        rval = s
    return rval

z = re.sub("("+l+")",do_repl,e)
# bonus: leading blanks should be stripped even that's not the question
z= re.sub(r"\s*\n\s*","\n",z,re.DOTALL)
print(z)

输出:

Dear Mr. Foo, I would like to thank you.
Because Lt.-Col. Collins told me blah blah.
Bye.