如何在Python中去除标点符号?

9

I've a problem:

E.x. I have a sentence

s = "AAA? BBB. CCC!" 

所以,我这样做:
import string
table = str.maketrans('', '', string.punctuation)
s = [w.translate(table) for w in s]

没问题。我的新句子是:

s = "AAA BBB CCC"

但是,如果我输入的句子是:

s = "AAA? BBB. CCC! DDD.EEE"

在删除标点符号后,我将使用以下相同的方法:

s = "AAA BBB CCC DDDEEE"

但需要:

s = "AAA BBB CCC DDD EEE"

有什么想法/方法可以解决这个问题吗?

@9769953 抱歉!这是我的错误!当然我想全部删除!(编辑) - ctrlaltdel
为什么不直接使用以下代码:s = [w if w not in string.punctuation else ' ' for w in s] - Luv
@Luv,这将导致在标点符号立即位于两个单词之间的情况下将合并这两个单词。 - Karan Shishoo
@casualcoder 不是的,因为你用一个空格替换了标点符号。 - Luv
@Luv,我没有看到 ' ' 中的空格,这样你有时会在单词之间有两个空格的情况。 - Karan Shishoo
8个回答

8

string.punctuation 包含以下字符:

'!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'

您可以使用 translate 和 maketrans 函数将标点符号映射为空值(替换)。

import string

'AAA? BBB. CCC! DDD.EEE'.translate(str.maketrans('', '', string.punctuation))

输出:

'AAA BBB CCC DDDEEE'

3
我认为他要求不同的输出。 - Jubick
根据语言的不同,它会留下许多标点符号和特殊字符。 - horace

5

试试这段代码:

import re

input_str = "AAA? BBB. CCC! DDD.EEE"
output_str = re.sub('[^A-Za-z0-9]+', ' ', input_str)
print output_str

'AAA BBB CCC DDD EEE'


1
与@casualcoder上面指出的问题相同。单词之间有多个空格。 - Luv
使用 r'[^\w]+(\s+|$)' 来处理一些边缘情况,并且加上 .strip(),否则如果最后一个单词以标点符号结尾,则会多出一个空格。 - Burhan Khalid
1
注意:这样可以删除特殊字符,如ß,以及具有图形信号(如ü,ú)的字符,因此根据您的语言,这不是一个好选择。 - Laura Corssac

4
你也可以这样做:
punctuation = "!@#$%^&*()_+<>?:.,;"  # add whatever you want

s = "AAA? BBB. CCC!" 
for c in s:
    if c in punctuation:
        s = s.replace(c, "")

print(s)

>>> "AAA BBB CCC"

2

使用:

import re

" ".join(re.split('\W+', s))

这将把字符串按所有非单词字符分割,然后通过单个空格连接各个子字符串。

实际上,在Python中,\W包括单词构成字符和非单词字符。 - Andj
@Andj 有趣。但是你在这里所说的“构词字符”是什么意思? - 9769953
\w 的 Unicode 定义为 [\p{alpha}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control}]。re 模块将其定义为大部分 \p{alpha},所有的 \p{digit} 和一个 \p{gc=Connector_Punctuation}。因此,所有的标记和连接控制符都被剥离了。 - Andj
采用模式pattern = re.compile(r'[^\w]', re.U),并使用text='မြန်မာစကား'进行re.sub(pattern, "", text),您将得到结果'မနမစက'。所有中央辅音和依赖元音都被去掉了。个人认为,中央辅音和依赖元音是可以构成单词的字符。同时尝试text = unicodedata.normalize("NFD", "français"),结果为'francais'。因此,组合变音符号被Re视为非单词形成字符。 - Andj
显然,你可以使用pattern = re.compile(r'[\W]')代替pattern = re.compile(r'[^\w]'。结果是相同的。此外,在我的平台上,正则表达式标志re.U并没有真正添加任何内容。 - Andj

1

这是一种使用 str.strip 和简单迭代的方法。

示例:

from string import punctuation

s = "AAA? BBB. CCC! DDD.EEE"

def cleanString(strval):
    return "".join(" " if i in punctuation else i for i in strval.strip(punctuation))

s = " ".join(cleanString(i) for i in s.split())
print(s)

输出:

AAA BBB CCC DDD EEE

0

我知道并非每个人都有这种情况,但我正在编写一个国际化应用程序,这需要更多的工作量。这是我想到的:

[编辑以添加“导入正则表达式”] - 感谢Andj

import regex

random_string = "~`!ќ®†њѓѕў‘“ъйжюёф №%:,)( ЛПМКё…∆≤≥“™ƒђ≈≠»"

clean_string = regex.sub( r'[^\w\s]', '', random_string )

print( clean_string )

结果为:

ќњѓѕўъйжюёф  ЛПМКёƒђ

这适用于许多语言中的广泛字母表和特殊字符。我已经在键盘上测试了几种语言,包括每个特殊字符和一些常规字符。仍需要去除一些特殊标记,这样就无法检测到。

简单而强大。希望能对某人有所帮助。


我正在编写的应用程序之一的功能是减少文件名生成中的错误。请详细说明。 - horace
1
以文件名kɔ̈ɔ̈r.png为例(我选择它是因为我在我的电脑上有一个这样的文件)。它使用了两个组合变音符号。在NFC、NFKC、NFKC_CF、NFD和NFKD中都是相同的。你上面的正则表达式模式将进行以下转换:kɔ̈ɔ̈r -> kɔɔr。更有问题的是,对于一个名为မြန်မာစာ.md的文件,မြန်မာစာ会被转换为မနမစ,即完全无法识别原始文件名。如果你受到LCG的限制,情况会稍微容易一些,但NFD或NFKD会引起麻烦。 - Andj
我处理多语言数据,可能是任何语言。我倾向于使用针对特定Python版本的虚拟环境。这意味着我也针对特定版本的Unicode进行了定位,因为每个Python版本都使用不同版本的Unicode。为确保最广泛的兼容性并处理边缘情况,我安装了针对我正在使用的Unicode版本构建的最新版本的regex。如果icu4c版本更高,则使用UnicodeSet符号来使我能够定位特定版本的Unicode字符集。 - Andj
如果我理解你的评论,\p{Cyrillic}是正则表达式模块的字面表达式。我会看一下。但是现在我们有几种语言,这会变得棘手。 - horace
我在这里开了一个问答主题:https://dev59.com/9qtMpogBymzxlkE8GMSV - horace
显示剩余13条评论

0

试试这个:

import string
exclude = set(string.punctuation)
exclude.remove(".")
doc = "AAA? BBB. CCC! DDD.EEE"
for punctuation in exclude:
    doc = doc.replace(punctuation,"")
doc = doc.replace("."," ")
doc = doc.split()
print(" ".join(doc))

0

看看这个:

if __name__ == "__main__":
    test_string = "AAA? BBB. CCC! DDD.EEE"
    result = "".join((char if char.isalpha() else " ") for char in test_string)
    print(result)


Result: AAA  BBB  CCC  DDD EEE

1
这将添加额外的空格。 - Burhan Khalid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接