仅在正则表达式中执行此操作并不漂亮,也不是最好的解决方案,但是,就在这里!你最好做一个多步骤的方法。我所做的是确定所有可能的情况,并选择找到没有替换字符串的解决方案,因为您并不总是用空格替换字符。
规则
- 非“堆叠”缩写
- 这些位置类似于
A. B. 或W. & J.,但不是C.M. & B.B.
- 我已将这些位置标识为缩写部分(例如
A.)前后存在的位置,但后者后面没有另一个字母字符
- 前面的空格
- 这些位置在您的文本中不存在,但如果非字母字符前面有一个空格,后面没有空格(比如在行尾),则可能存在这些位置
- 在这些情况下,我们匹配第一个空格之后的字符
- 进行空间
- 这些位置类似于
& 和J. 中的点
- 我们匹配这些示例中最后一个空格之前的字符
- 没有空格
- 这些位置类似于
'LOVE(该字符串中的撇号)
- 我们只匹配非字母非空白字符
正则表达式
实现此目的的一体化正则表达式如下:
See regex in use here
(?<=\b[a-z])[^a-z]+(?=[a-z]\b(?![^a-z][a-z]))|(?<= ) *(?:\.com\b|[^a-z\s]+) *| *(?:\.com\b|[^a-z\s]+) *(?= )|(?<! )(?:\.com\b|[^a-z\s]+)(?! )
工作方式如下(分解为每个交替):
-
(?<=\b[a-z])[^a-z]+(?=[a-z]\b(?![^a-z][a-z])) 匹配 A. 和 B. 之间的非字母字符,但不匹配 A. 和 B.B
-
(?<=\b[a-z]) 正向向后看,确保前面是一个字母字符,并在其左侧声明一个单词边界位置
-
[^a-z]+ 匹配任何非字母字符一次或多次
-
(?=[a-z]\b(?![^a-z][a-z])) 正向前瞻确保以下内容存在
-
[a-z]\b 匹配任何字母字符并在其右侧声明一个单词边界位置
-
(?![^a-z][a-z]) 否定前瞻确保后面的不是非字母字符后跟一个字母字符
-
(?<= ) *(?:\.com\b|[^a-z\s]+) * 确保前面有一个空格,然后匹配任何空格,.com 或任何非单词非空白字符一次或多次,然后匹配任何空格
-
(?<= ) 正向向后看,确保前面有一个空格
-
* 匹配任意数量的空格
-
(?:\.com\b|[^a-z\s]+) 匹配 .com 并确保后面是非单词字符,或匹配任何非单词非空白字符一次或多次
-
* 匹配任意数量的空格
-
*(?:\.com\b|[^a-z\s]+) *(?= ) 匹配任何空格、.com 或任何非单词非空白字符一次或多次,然后匹配任何空格,然后确保后面有空格
- 与上一个相同,但不是在开始时正面向后看,而是在结尾处正面向前看
-
(?<! )(?:\.com\b|[^a-z\s]+)(?! ) 匹配 .com 或任何非字母非空白字符一次或多次,确保其周围没有空格
代码
See code in use here
import re
strings = [
"'W. & J. JOHNSON LMT.COM'",
"'NORTH ROOF & WORKS CO. LTD.'",
"'DAVID DOE & CO., LIMITED'",
"'GEORGE TV & APPLIANCE LTD.'",
"'LOVE BROS. & OTHERS LTD.'",
"'A. B. & MICHAEL CLEAN CO. LTD.'",
"'C.M. & B.B. CLEANER INC.'"
]
r = re.compile(r'(?<=\b[a-z])[^a-z]+(?=[a-z]\b(?![^a-z][a-z]))|(?<= ) *(?:\.com\b|[^a-z\s]+) *| *(?:\.com\b|[^a-z\s]+) *(?= )|(?<! )(?:\.com\b|[^a-z\s]+)(?! )', re.IGNORECASE)
def transform(word):
return re.sub(r, '', word)
for s in strings:
print(transform(s))
输出:
WJ JOHNSON LMT
NORTH ROOF WORKS CO LTD
DAVID DOE CO LIMITED
GEORGE TV APPLIANCE LTD
LOVE BROS OTHERS LTD
AB MICHAEL CLEAN CO LTD
CM BB CLEANER INC
编辑
使用回调,您可以扩展此逻辑以包含我的答案下方评论中提到的特殊情况,以匹配特定情况并进行条件替换。
这些特殊情况包括:
-
FONTAINE'S 到 FONTAINE
-
PREMIUM-FIT AUTO 到 PREMIUM FIT AUTO
-
62325 W.C. 到 62325 WC
我为正则表达式添加了一个新的替代:(\b[\'-]\b(?:[a-z\d] )?) 以在字母之间捕获 'S 或 -(也可以是 -S 或类似的)并使用回调将其替换为空格(如果捕获组存在) .
我仍然建议使用多个正则表达式来完成此操作,但我想表明使用单个模式是可能的。
See code in use here
import re
strings = [
"'W. & J. JOHNSON LMT.COM'",
"'NORTH ROOF & WORKS CO. LTD.'",
"'DAVID DOE & CO., LIMITED'",
"'GEORGE TV & APPLIANCE LTD.'",
"'LOVE BROS. & OTHERS LTD.'",
"'A. B. & MICHAEL CLEAN CO. LTD.'",
"'C.M. & B.B. CLEANER INC.'",
"'FONTAINE'S PREMIUM-FIT AUTO 62325 W.C.'"
]
r = re.compile(r'(?<=\b[a-z\d])[^a-z\d]+(?=[a-z\d]\b(?![^a-z\d][a-z\d]))|(?<= ) *(?:\.com\b|[^a-z\d\s]+) *| *(?:\.com\b|[^a-z\d\s]+) *(?= )|(\b[\'-]\b(?:[a-z\d] )?)|(?<! )(?:\.com\b|[^a-z\d\s]+)(?! )', re.IGNORECASE)
def repl(m):
return ' ' if m.group(1) else ''
for s in strings:
print(r.sub(repl, s))