删除字母Python之间的符号

时间:2017-10-31 15:04:09

标签: python regex string

我想从字符串中删除某些符号。我只想删除字母之间的符号。如果我的问题不够清楚,那么这里有一些例子: 符号为@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, "")

我知道这个脚本会替换所有符号

3 个答案:

答案 0 :(得分:3)

Regular expressions一开始肯定是可怕的,但值得尝试学习它们,因为它们最终非常有用。在这种情况下你想要的是:

import re
string = re.sub(r'([a-zA-Z])[@31!]+(?=[a-zA-Z])', r'\1', string)

Let's look at what this does.

re.substr.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)

代码

See this regex in use here

(?<=[a-z])[@13!]+(?=[a-z])

结果

输入

@@He11o Wor1d!
!!T3ach !m3
@13!

输出

@@Heo Word!
!!Tach !m3
@13!

说明

  • (?<=[a-z])肯定的背后隐藏确保az
  • 之间的字母前面的内容
  • [@13!]+匹配集@13!
  • 中的一个或多个字符
  • (?=[a-z])确保以下是az
  • 之间的字母的正面预测

使用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)