如何用模式替换字符串的一部分

时间:2018-03-02 01:27:38

标签: python string replace

例如,字符串是" abbacdeffel"而且模式是" xyyx"替换为" 1234"

所以它会来自" abbacdeffel"到" 1234cd1234l"

我试图想出来但我无法想出任何东西。起初我想也许字典可以帮助但仍然没有想到任何事情。

3 个答案:

答案 0 :(得分:3)

您可以使用正则表达式或更常见的正则表达式来完成您要做的事情。编程中的正则表达式使您能够从字符串中提取所需内容以及所需内容。 在您的情况下,您希望将字符串与模式abba匹配,因此使用以下正则表达式:

(\w+)(\w+)\2\1

https://regex101.com/r/hP8lA3/1

您可以匹配两个单词组并使用反向引用来确保第二个组首先出现,然后是第一个组。

因此在python代码中实现它看起来像这样:

首先,在python中导入regex模块

import re

然后,声明你的变量

text = "abbacdeffel"

re.finditer返回一个iterable,因此您可以遍历所有组

matches = re.finditer(r"(\w)(\w)\2\1", text)

浏览正则表达式找到的所有匹配项,并用" 1234"

替换模式
for match in matches:
  text = text.replace(match.group(0), "1234")

用于调试:

print(text)

完整代码:

import re

text = "abbacdeffel"

matches = re.finditer(r"(\w)(\w)\2\1", text)

for match in matches:
    text = text.replace(match.group(0), "1234")

print(text)

您可以在此处详细了解正则表达式:https://regexone.com/references/python

答案 1 :(得分:1)

这里有my attempt

([a-zA-Z])(?!\1)([a-zA-Z])\2\1

假设您只想匹配字母(如果是其他范围,请根据需要同时更改[a-zA-Z],我们有:

([a-zA-Z])

找到第一个字符,并记下它,以便我们稍后可以使用\1来引用它。

(?!\1)

检查下一个字符是否与第一个字符不同,但不推进搜索指针。这是为了防止aaaa被接受。如果aaaa没问题,只需删除此子表达式。

([a-zA-Z])

找到第二个字符,并记下它,以便我们稍后可以使用\2来引用它。

\2\1

现在再次找到第二个,然后再找到第一个,所以我们匹配完整的abba模式。

最后,要执行替换操作,完整命令将是:

import re
re.sub(r'([a-zA-Z])(?!\1)([a-zA-Z])\2\1',
       '1234',
       'abbacdeffelzzzz')

正则表达式模式开头的r是为了防止Python处理反斜杠。没有它,你需要做:

import re
re.sub('([a-zA-Z])(?!\\1)([a-zA-Z])\\2\\1',
       '1234',
       'abbacdeffelzzzz')

现在,我看到规范已扩展为用户定义的模式;这是一些将构建该模式的代码:

import re

def make_re(pattern, charset):
    result = ''
    seen = []
    for c in pattern:
        # Is this a letter we've seen before?
        if c in seen:
            # Yes, so we want to match the captured pattern
            result += '\\' + str(seen.index(c)+1)
        else:
            # No, so match a new character from the charset,
            # but first exclude already matched characters
            for i in xrange(len(seen)):
                result += '(?!\\' + str(i + 1) + ')'
            result += '(' + charset + ')'
            # Note we have seen this letter
            seen.append(c)
    return result

print re.sub(make_re('xzzx', '\\d'), 'abba', 'abba1221b99999889')
print re.sub(make_re('xyzxyz', '[a-z]'), '123123', 'abcabc zyxzyyx zyzzyz')

输出:

abbaabbab9999abba
123123 zyxzyyx zyzzyz

答案 2 :(得分:1)

新版代码(存在错误):

def replace_with_pattern(pattern, line, replace):
    from collections import OrderedDict
    set_of_chars_in_pattern = set(pattern)

    indice_start_pattern = 0
    output_line = ""
    while indice_start_pattern < len(line):
        potential_end_pattern = indice_start_pattern + len(pattern)
        subline               = line[indice_start_pattern:potential_end_pattern] 
        print(subline)
        set_of_chars_in_subline = set(subline)
        if len(set_of_chars_in_subline)!= len(set_of_chars_in_pattern):
            output_line += line[indice_start_pattern]
            indice_start_pattern +=1
            continue

        map_of_chars = OrderedDict()
        liste_of_chars_in_pattern = []
        for char in pattern:
            if char not in liste_of_chars_in_pattern:
                liste_of_chars_in_pattern.append(char)
        print(liste_of_chars_in_pattern)

        for subline_char in subline:
            if subline_char not in map_of_chars.values():
                map_of_chars[liste_of_chars_in_pattern.pop(0)] =subline_char 

        print(map_of_chars)
        wanted_subline = ""
        for char_of_pattern in pattern:
            wanted_subline += map_of_chars[char_of_pattern]
        print("wanted_subline =" + wanted_subline)
        if subline == wanted_subline:
            output_line += replace
            indice_start_pattern += len(pattern)
        else:
            output_line += line[indice_start_pattern]
            indice_start_pattern += 1
    return output_line

一些测试:

test1 = replace_with_pattern("xyyx", "abbacdeffel", "1234")
test2 = replace_with_pattern("abbacdeffel", "abbacdeffel", "1234")
print(test1, test2)

=&GT; 1234cd1234l 1234