简体   繁体   English

从 Python 中的字符串中删除特定字符

[英]Remove specific characters from a string in Python

I'm trying to remove specific characters from a string using Python.我正在尝试使用 Python 从字符串中删除特定字符。 This is the code I'm using right now.这是我现在正在使用的代码。 Unfortunately it appears to do nothing to the string.不幸的是,它似乎对字符串没有任何作用。

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

How do I do this properly?我该如何正确执行此操作?

Strings in Python are immutable (can't be changed). Python 中的字符串是不可变的(不能更改)。 Because of this, the effect of line.replace(...) is just to create a new string, rather than changing the old one.因此, line.replace(...)作用只是创建一个新字符串,而不是更改旧字符串。 You need to rebind (assign) it to line in order to have that variable take the new value, with those characters removed.您需要将它重新绑定(分配)到line以便让该变量采用新值,并删除这些字符。

Also, the way you are doing it is going to be kind of slow, relatively.此外,相对而言,您这样做的方式会有点慢。 It's also likely to be a bit confusing to experienced pythonators, who will see a doubly-nested structure and think for a moment that something more complicated is going on.对于有经验的 Pythonators 来说,这也可能会有点混乱,他们会看到一个双重嵌套的结构,并会认为有更复杂的事情正在发生。

Starting in Python 2.6 and newer Python 2.x versions *, you can instead use str.translate , ( see Python 3 answer below ):从 Python 2.6 和更新的 Python 2.x 版本 * 开始,您可以改用str.translate ,(请参阅下面的Python 3 答案):

line = line.translate(None, '!@#$')

or regular expression replacement with re.sub或用re.sub替换正则表达式

import re
line = re.sub('[!@#$]', '', line)

The characters enclosed in brackets constitute a character class .括号中的字符构成一个字符类 Any characters in line which are in that class are replaced with the second parameter to sub : an empty string.在任何字符line ,其是在该类中被替换的第二个参数sub :一个空字符串。

Python 3 answer Python 3 答案

In Python 3, strings are Unicode.在 Python 3 中,字符串是 Unicode。 You'll have to translate a little differently.您将不得不以稍微不同的方式翻译。 kevpie mentions this in a comment on one of the answers, and it's noted in the documentation for str.translate . kevpie 在对其中一个答案的评论中提到了这一点,并在str.translate文档中str.translate

When calling the translate method of a Unicode string, you cannot pass the second parameter that we used above.在调用 Unicode 字符串的translate方法时,不能传递我们上面使用的第二个参数。 You also can't pass None as the first parameter.您也不能将None作为第一个参数传递。 Instead, you pass a translation table (usually a dictionary) as the only parameter.相反,您将转换表(通常是字典)作为唯一参数传递。 This table maps the ordinal values of characters (ie the result of calling ord on them) to the ordinal values of the characters which should replace them, or—usefully to us— None to indicate that they should be deleted.该表将字符的序数值(即对它们调用ord的结果)映射到应该替换它们的字符的序数值,或者——对我们有用—— None表示它们应该被删除。

So to do the above dance with a Unicode string you would call something like因此,要使用 Unicode 字符串进行上述舞蹈,您可以调用类似

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

Here dict.fromkeys and map are used to succinctly generate a dictionary containing这里使用dict.fromkeysmap来简洁地生成一个字典,其中包含

{ord('!'): None, ord('@'): None, ...}

Even simpler, as another answer puts it , create the translation table in place:更简单的是,正如另一个答案所说,在适当的位置创建翻译表:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

Or, as brought up by Joseph Lee , create the same translation table with str.maketrans :或者,正如Joseph Lee 所提出的,使用str.maketrans创建相同的转换表:

unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))

* for compatibility with earlier Pythons, you can create a "null" translation table to pass in place of None : * 为了与早期的 Python 兼容,您可以创建一个“空”转换表来代替None

import string
line = line.translate(string.maketrans('', ''), '!@#$')

Here string.maketrans is used to create a translation table , which is just a string containing the characters with ordinal values 0 to 255.这里string.maketrans用于创建一个转换表,它只是一个包含序号为 0 到 255 的字符的字符串。

Am I missing the point here, or is it just the following:我在这里错过了这一点,还是只是以下几点:

string = "ab1cd1ef"
string = string.replace("1", "") 

print(string)
# result: "abcdef"

Put it in a loop:把它放在一个循环中:

a = "a!b@c#d$"
b = "!@#$"
for char in b:
    a = a.replace(char, "")

print(a)
# result: "abcd"
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'

With re.sub regular expression使用re.sub正则表达式

Since Python 3.5, substitution using regular expressions re.sub became available:从 Python 3.5 开始,可以使用正则表达式re.sub替换:

import re
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

Example例子

import re
line = 'Q: Do I write ;/.??? No!!!'
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

'QDoIwriteNo'

Explanation解释

In regular expressions (regex), |正则表达式(regex)中, | is a logical OR and \\ escapes spaces and special characters that might be actual regex commands.是逻辑 OR 和\\转义空格和可能是实际正则表达式命令的特殊字符。 Whereas sub stands for substitution, in this case with the empty string '' .sub代表替换,在本例中为空字符串''

For the inverse requirement of only allowing certain characters in a string, you can use regular expressions with a set complement operator [^ABCabc] .对于允许字符串中的某些字符的相反要求,您可以使用带有集合补码运算符[^ABCabc]正则表达式。 For example, to remove everything except ascii letters, digits, and the hyphen:例如,要删除除 ascii 字母、数字和连字符以外的所有内容:

>>> import string
>>> import re
>>>
>>> phrase = '  There were "nine" (9) chick-peas in my pocket!!!      '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)

'Therewerenine9chick-peasinmypocket'

From the python regular expression documentation :来自python 正则表达式文档

Characters that are not within a range can be matched by complementing the set.不在范围内的字符可以通过对集合进行补充来匹配。 If the first character of the set is '^' , all the characters that are not in the set will be matched.如果集合的第一个字符是'^' ,则将匹配所有不在集合中的字符。 For example, [^5] will match any character except '5', and [^^] will match any character except '^' .例如, [^5]将匹配除 '5' 之外的任何字符,而[^^]将匹配除'^'之外'^'任何字符。 ^ has no special meaning if it's not the first character in the set.如果^不是集合中的第一个字符,则没有特殊含义。

The asker almost had it.提问者几乎得到了它。 Like most things in Python, the answer is simpler than you think.与 Python 中的大多数事情一样,答案比您想象的要简单。

>>> line = "H E?.LL!/;O:: "  
>>> for char in ' ?.!/;:':  
...  line = line.replace(char,'')  
...
>>> print line
HELLO

You don't have to do the nested if/for loop thing, but you DO need to check each character individually.您不必执行嵌套的 if/for 循环操作,但确实需要单独检查每个字符。

line = line.translate(None, " ?.!/;:")
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'

Strings are immutable in Python.字符串在 Python 中是不可变的。 The replace method returns a new string after the replacement. replace方法在替换后返回一个新字符串。 Try:尝试:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')

This is identical to your original code, with the addition of an assignment to line inside the loop.这与您的原始代码相同,只是在循环内添加了对line的赋值。

Note that the string replace() method replaces all of the occurrences of the character in the string, so you can do better by using replace() for each character you want to remove, instead of looping over each character in your string.请注意,字符串replace()方法会替换字符串中出现的所有字符,因此您可以通过对要删除的每个字符使用replace()来做得更好,而不是遍历字符串中的每个字符。

I was surprised that no one had yet recommended using the builtin filter function.我很惊讶还没有人推荐使用内置过滤器功能。

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

Say we want to filter out everything that isn't a number.假设我们要过滤掉所有不是数字的东西。 Using the filter builtin method "...is equivalent to the generator expression (item for item in iterable if function(item))" [ Python 3 Builtins: Filter ]使用过滤器内置方法“...相当于生成器表达式(如果函数(项目)中的项目的项目)”[ Python 3 内置:过滤器]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

In Python 3 this returns在 Python 3 中,这将返回

    >>  <filter object @ hex>

To get a printed string,要获得打印的字符串,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

I am not sure how filter ranks in terms of efficiency but it is a good thing to know how to use when doing list comprehensions and such.我不确定过滤器在效率方面的排名如何,但知道在进行列表理解等时如何使用是一件好事。

UPDATE更新

Logically, since filter works you could also use list comprehension and from what I have read it is supposed to be more efficient because lambdas are the wall street hedge fund managers of the programming function world.从逻辑上讲,由于过滤器有效,你也可以使用列表理解,从我读到的内容来看,它应该更有效,因为 lambda 是编程函数世界的华尔街对冲基金经理。 Another plus is that it is a one-liner that doesnt require any imports.另一个优点是它是一种单线,不需要任何进口。 For example, using the same string 's' defined above,例如,使用上面定义的相同字符串 's',

      num = "".join([i for i in s if i.isdigit()])

That's it.就是这样。 The return will be a string of all the characters that are digits in the original string.返回将是原始字符串中所有数字字符的字符串。

If you have a specific list of acceptable/unacceptable characters you need only adjust the 'if' part of the list comprehension.如果您有可接受/不可接受字符的特定列表,则只需调整列表理解的“if”部分。

      target_chars = "".join([i for i in s if i in some_list]) 

or alternatively,或者,

      target_chars = "".join([i for i in s if i not in some_list])

Using filter , you'd just need one line使用filter ,你只需要一行

line = filter(lambda char: char not in " ?.!/;:", line)

This treats the string as an iterable and checks every character if the lambda returns True :这将字符串视为可迭代的,并检查lambda返回True每个字符:

 >>> help(filter) Help on built-in function filter in module __builtin__: filter(...) filter(function or None, sequence) -> list, tuple, or string Return those items of sequence for which function(item) is true. If function is None, return the items that are true. If sequence is a tuple or string, return the same type, else return a list.

Here's some possible ways to achieve this task:以下是完成此任务的一些可能方法:

def attempt1(string):
    return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])


def attempt2(string):
    for v in ("a", "e", "i", "o", "u"):
        string = string.replace(v, "")
    return string


def attempt3(string):
    import re
    for v in ("a", "e", "i", "o", "u"):
        string = re.sub(v, "", string)
    return string


def attempt4(string):
    return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")


for attempt in [attempt1, attempt2, attempt3, attempt4]:
    print(attempt("murcielago"))

PS: Instead using " ?.!/;:" the examples use the vowels... and yeah, "murcielago" is the Spanish word to say bat... funny word as it contains all the vowels :) PS:而不是使用“ ?.!/;:”示例使用元音...是的,“murcielago”是西班牙语单词,表示 bat... 有趣的词,因为它包含所有元音 :)

PS2: If you're interested on performance you could measure these attempts with a simple code like: PS2:如果你对性能感兴趣,你可以用一个简单的代码来衡量这些尝试,比如:

import timeit


K = 1000000
for i in range(1,5):
    t = timeit.Timer(
        f"attempt{i}('murcielago')",
        setup=f"from __main__ import attempt{i}"
    ).repeat(1, K)
    print(f"attempt{i}",min(t))

In my box you'd get:在我的盒子里你会得到:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

So it seems attempt4 is the fastest one for this particular input.因此,对于此特定输入,尝试 4 似乎是最快的。

Here's my Python 2/3 compatible version.这是我的 Python 2/3 兼容版本。 Since the translate api has changed.由于翻译api已更改。

def remove(str_, chars):
    """Removes each char in `chars` from `str_`.

    Args:
        str_: String to remove characters from
        chars: String of to-be removed characters

    Returns:
        A copy of str_ with `chars` removed

    Example:
            remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
    """
    try:
        # Python2.x
        return str_.translate(None, chars)
    except TypeError:
        # Python 3.x
        table = {ord(char): None for char in chars}
        return str_.translate(table)

Try this one:试试这个:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

This method works well in Python 3此方法在 Python 3 中运行良好

You have to reassign your str variable: 您必须重新分配str变量:

for char in line:
if char in " ?.!/;:":
    line = line.replace(char,'')
#!/usr/bin/python
import re

strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr

You can also use a function in order to substitute different kind of regular expression or other pattern with the use of a list.您还可以使用函数来使用列表替换不同类型的正则表达式或其他模式。 With that, you can mixed regular expression, character class, and really basic text pattern.有了它,您可以混合正则表达式、字符类和真正基本的文本模式。 It's really useful when you need to substitute a lot of elements like HTML ones.当您需要替换很多元素(如 HTML 元素)时,它非常有用。

*NB: works with Python 3.x *注意:适用于 Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

In the function string_cleanup, it takes your string x and your list notwanted as arguments.在函数 string_cleanup 中,它将字符串 x 和不需要的列表作为参数。 For each item in that list of elements or pattern, if a substitute is needed it will be done.对于该元素或模式列表中的每个项目,如果需要替换,它将完成。

The output:输出:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean

My method I'd use probably wouldn't work as efficiently, but it is massively simple.我使用的方法可能不会那么有效,但它非常简单。 I can remove multiple characters at different positions all at once, using slicing and formatting.我可以使用切片和格式一次删除不同位置的多个字符。 Here's an example:下面是一个例子:

words = "things"
removed = "%s%s" % (words[:3], words[-1:])

This will result in 'removed' holding the word 'this'.这将导致 'removed' 保留单词 'this'。

Formatting can be very helpful for printing variables midway through a print string.格式化对于在打印字符串中途打印变量非常有帮助。 It can insert any data type using a % followed by the variable's data type;它可以使用%后跟变量的数据类型插入任何数据类型; all data types can use %s , and floats (aka decimals) and integers can use %d .所有数据类型都可以使用%s ,浮点数(又名小数)和整数可以使用%d

Slicing can be used for intricate control over strings.切片可用于对字符串进行复杂的控制。 When I put words[:3] , it allows me to select all the characters in the string from the beginning (the colon is before the number, this will mean 'from the beginning to') to the 4th character (it includes the 4th character).当我输入words[:3] 时,它允许我选择字符串中从开头(冒号在数字之前,这意味着“从开头到”)到第 4 个字符(包括第 4 个)的所有字符特点)。 The reason 3 equals till the 4th position is because Python starts at 0. Then, when I put word[-1:] , it means the 2nd last character to the end (the colon is behind the number). 3 等于第 4 位的原因是因为 Python 从 0 开始。然后,当我输入word[-1:] 时,它表示最后的第二个字符(冒号在数字后面)。 Putting -1 will make Python count from the last character, rather than the first.输入 -1 将使 Python 从最后一个字符开始计数,而不是从第一个字符开始计数。 Again, Python will start at 0. So, word[-1:] basically means 'from the second last character to the end of the string.同样,Python 将从 0 开始。因此, word[-1:]基本上意味着 '从倒数第二个字符到字符串的末尾。

So, by cutting off the characters before the character I want to remove and the characters after and sandwiching them together, I can remove the unwanted character.因此,通过切断我想要删除的字符之前的字符和之后的字符并将它们夹在一起,我可以删除不需要的字符。 Think of it like a sausage.把它想象成香肠。 In the middle it's dirty, so I want to get rid of it.中间很脏,所以我想摆脱它。 I simply cut off the two ends I want then put them together without the unwanted part in the middle.我只是切断了我想要的两端,然后将它们放在一起,中间没有不需要的部分。

If I want to remove multiple consecutive characters, I simply shift the numbers around in the [] (slicing part).如果我想删除多个连续字符,我只需在 [](切片部分)中移动数字。 Or if I want to remove multiple characters from different positions, I can simply sandwich together multiple slices at once.或者,如果我想从不同位置删除多个字符,我可以简单地一次将多个切片夹在一起。

Examples:例子:

 words = "control"
 removed = "%s%s" % (words[:2], words[-2:])

removed equals 'cool'.删除等于“酷”。

words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])

removed equals 'macs'.删除等于'macs'。

In this case, [3:5] means character at position 3 through character at position 5 (excluding the character at the final position).在这种情况下, [3:5]表示位置3 到位置5 的字符(不包括最终位置的字符)。

Remember, Python starts counting at 0 , so you will need to as well.请记住, Python 从 0 开始计数,因此您也需要这样做。

How about this:这个怎么样:

def text_cleanup(text):
    new = ""
    for i in text:
        if i not in " ?.!/;:":
            new += i
    return new

In Python 3.5在 Python 3.5 中

eg,例如,

os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))

To remove all the number from the string从字符串中删除所有数字

>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'

You could use the re module's regular expression replacement.您可以使用 re 模块的正则表达式替换。 Using the ^ expression allows you to pick exactly what you want from your string.使用 ^ 表达式可以让您从字符串中准确选择您想要的内容。

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

Output to this would be "Thisisabsurd".对此的输出将是“Thisisabsurd”。 Only things specified after the ^ symbol will appear.只有在 ^ 符号后指定的内容才会出现。

The string method replace does not modify the original string.字符串方法replace不会修改原始字符串。 It leaves the original alone and returns a modified copy.它保留原件并返回修改后的副本。

What you want is something like: line = line.replace(char,'')你想要的是这样的: line = line.replace(char,'')

def replace_all(line, )for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
    return line

However, creating a new string each and every time that a character is removed is very inefficient.但是,每次删除一个字符时都创建一个新字符串是非常低效的。 I recommend the following instead:我建议改为:

def replace_all(line, baddies, *):
    """
    The following is documentation on how to use the class,
    without reference to the implementation details:

    For implementation notes, please see comments begining with `#`
    in the source file.

    [*crickets chirp*]

    """

    is_bad = lambda ch, baddies=baddies: return ch in baddies
    filter_baddies = lambda ch, *, is_bad=is_bad: "" if is_bad(ch) else ch
    mahp = replace_all.map(filter_baddies, line)
    return replace_all.join('', join(mahp))

    # -------------------------------------------------
    # WHY `baddies=baddies`?!?
    #     `is_bad=is_bad`
    # -------------------------------------------------
    # Default arguments to a lambda function are evaluated
    # at the same time as when a lambda function is
    # **defined**.
    #
    # global variables of a lambda function
    # are evaluated when the lambda function is
    # **called**
    #
    # The following prints "as yellow as snow"
    #
    #     fleece_color = "white"
    #     little_lamb = lambda end: return "as " + fleece_color + end
    #
    #     # sometime later...
    #
    #     fleece_color = "yellow"
    #     print(little_lamb(" as snow"))
    # --------------------------------------------------
replace_all.map = map
replace_all.join = str.join

If you want your string to be just allowed characters by using ASCII codes, you can use this piece of code:如果您希望您的字符串只允许使用 ASCII 码的字符,您可以使用这段代码:

for char in s:
    if ord(char) < 96 or ord(char) > 123:
        s = s.replace(char, "")

It will remove all the characters beyond a....z even upper cases.它将删除 a....z 之外的所有字符,甚至是大写。

Below one.. with out using regular expression concept..下面一个..不使用正则表达式概念..

ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring

Even the below approach works即使下面的方法也有效

line = "a,b,c,d,e"
alpha = list(line)
        while ',' in alpha:
            alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)

output: abcde输出: abcde

I'm trying to remove specific characters from a string using Python.我正在尝试使用Python从字符串中删除特定字符。 This is the code I'm using right now.这是我现在正在使用的代码。 Unfortunately it appears to do nothing to the string.不幸的是,它似乎对字符串没有任何作用。

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

How do I do this properly?如何正确执行此操作?

Recursive split: s=string ;递归拆分: s=string ; chars=chars to remove字符=要删除的字符

def strip(s,chars):
if len(s)==1:
    return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) +  strip(s[int(len(s)/2):len(s)],chars)

example:例子:

print(strip("Hello!","lo"))    #He!

# for each file on a directory, rename filename # 对于目录中的每个文件,重命名文件名

   file_list = os.listdir (r"D:\Dev\Python")

   for file_name in file_list:

       os.rename(file_name, re.sub(r'\d+','',file_name))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM