我想从字符串中删除某些符号。我只想删除字母之间的符号。如果我的问题不够清楚,那么这里有一些例子:
符号为@31!
输入
@@He11o Wor1d!
!!T3ach !m3
@13!
预期输出
@@Heo Word!
!!Tach !m3
@13!
你能指出我正确的方向吗?我不希望你为我做这件事。我知道这可以通过正则表达式和for循环来完成,但对于像我这样的初学者来说,正则表达式看起来有点困难。这就是我现在正在做的事情:
string = '@@He11o Wor1d!'
string_copy = string
symbols = "@31!"
for char in symbols:
string_copy = string_copy.replace(char, "")
我知道这个脚本会替换所有符号
答案 0 :(得分:3)
Regular expressions一开始肯定是可怕的,但值得尝试学习它们,因为它们最终非常有用。在这种情况下你想要的是:
import re
string = re.sub(r'([a-zA-Z])[@31!]+(?=[a-zA-Z])', r'\1', string)
re.sub
与str.replace
类似,但它使用正则表达式。
[a-zA-Z]
匹配任何字母。
[@31!]+
匹配列出的一个或多个符号。
+ 导致生成的RE匹配前一个RE的1次或多次重复。
(?=[a-zA-Z])
是一封信的先行断言。这意味着匹配后跟一个字母,但这封信不是匹配的一部分。
(?= ...) 匹配if ...匹配next,但不消耗任何字符串。这称为先行断言。例如,Isaac(?= Asimov)只有在跟随'Asimov'后才会匹配'Isaac'。
因此([a-zA-Z])[@31!]+(?=[a-zA-Z])
匹配一个字母,后跟列表中的一个或多个符号。这场比赛之后是一个字母,但比赛中不包括这封信。
\1
是对正则表达式中带括号的组的反向引用,在本例中为[a-zA-Z]
。这就是我们想要取代我们所发现的东西。
(字符串之前的r
s使它们成为原始字符串,这在使用正则表达式时通常会有所帮助。)
修改强>
正如@ctwheels指出的那样,you can also use a lookbehind assertion rather than a backreference:
string = re.sub(r'(?<=[a-zA-Z])[@31!]+(?=[a-zA-Z])', r'', string)
答案 1 :(得分:3)
这是正确的做法很棘手。虽然我通常更愿意避免使用正则表达式,除非它们是必要的,但这绝对是一种他们使 lot 更轻松的工作的情况。但无论如何,这是一个非正则表达式解决方案。
我们使用标准groupby
函数将输入字符串分为三类:&#39; A&#39;群组包含字母,&#39; S&#39;组包含特殊符号,&#39; O&#39;组包含其他任何内容。然后我们扫描组,将它们复制到result
列表,除非该组是&#39; S&#39;小组,它有一个&#39; A&#39;紧接在它之前并立即跟随它。最后,我们将复制的组连接回一个字符串。
为了便于检查以下群组,我们添加了一个&#34;假的&#34; ('O', '')
组到组列表的末尾。这样每个真正的小组都有以下小组。
from itertools import groupby
symbols = '@31!'
def keyfunc(c):
if c in symbols:
return 'S'
elif c.isalpha():
return 'A'
else:
return 'O'
def remove_symbols(s):
groups = [(k, ''.join(g)) for k, g in groupby(s, keyfunc)] + [('O', '')]
result = []
prev = 'O'
for i, (k, g) in enumerate(groups[:-1]):
# If a group of symbols has an alpha group on both sides, don't copy it
if not (k == 'S' and prev == 'A' and groups[i+1][0] == 'A'):
result.append(g)
prev = k
return ''.join(result)
# Test
data = '''\
@@He11o Wor1d!
!!T3ach !m3
@13!
lala@@@@
'''
expected = '''\
@@Heo Word!
!!Tach !m3
@13!
lala@@@@
'''
print('Data')
print(data)
print('Expected')
print(expected)
print('Output')
for s in data.splitlines():
print(remove_symbols(s))
<强>输出强>
Data
@@He11o Wor1d!
!!T3ach !m3
@13!
lala@@@@
Expected
@@Heo Word!
!!Tach !m3
@13!
lala@@@@
Output
@@Heo Word!
!!Tach !m3
@13!
lala@@@@
答案 2 :(得分:2)
(?<=[a-z])[@13!]+(?=[a-z])
@@He11o Wor1d!
!!T3ach !m3
@13!
@@Heo Word!
!!Tach !m3
@13!
(?<=[a-z])
肯定的背后隐藏确保a
和z
[@13!]+
匹配集@13!
(?=[a-z])
确保以下是a
和z
使用i
标志使模式不区分大小写,因此a-z
也匹配A-Z
import re
regex = r"(?<=[a-z])[@13!]+(?=[a-z])"
result = re.sub(regex, "", string, 0, re.IGNORECASE)
# re.IGNORECASE can be replaced with the shortened re.I
或(正则表达式中的标志,而不是传递给函数)
import re
regex = r"(?i)(?<=[a-z])[@13!]+(?=[a-z])"
result = re.sub(regex, "", string)