使用Python替换或交换文件中的子串

时间:2012-05-29 21:38:41

标签: python regex string

假设我在以下格式的ASCII文件中有一行:

{text1} {stringA} {text2} {stringB} {text3}

其中{stringA}{stringB}是感兴趣的子字符串。我们分别称它们为“A”和“B”。字符串{text1}{text2}{text3}是任何长度(可能为空)的字符串,不包含A或B.

我想在Python中做的只是交换A和B,使得该行来自

{text1} {stringA} {text2} {stringB} {text3}

{text1} {stringB} {text2} {stringA} {text3}

我很感激这里有任何帮助。我认为通过获得这个问题的帮助,它将帮助我学习如何更好地使用Python中的正则表达式。

请注意,{text1}{text2}{text3}是未知字符串。

我们确切地知道子串A和B.我们知道A在行中的B之前。但是,我们不知道它们之前/之间/之后是什么(如果有的话)。

示例(A = John,B = Tim):

(1)这:

“我告诉约翰把包给蒂姆。”

更改为:

“我告诉蒂姆把这个包给了约翰。”

(2)这:

“约翰向蒂姆问好。”

更改为:

“蒂姆向约翰问好。”

(3)这:

“约翰!h9aghagTim”

更改为:

“添!h9aghagJohn”

2 个答案:

答案 0 :(得分:7)

>>> import re
>>> text = '{text1} {stringA} {text2} {stringB} {text3}'
>>> re.sub(r'(stringA)(.*)(stringB)', r'\3\2\1', text)
'{text1} {stringB} {text2} {stringA} {text3}'

stringAstringB替换为您感兴趣的子字符串,请注意,如果子字符串在正则表达式中具有特殊含义的字符,您可能需要re.escape()

测试用例:

>>> stringA = 'John'
>>> stringB = 'Tim'
>>> regex = re.compile(r'(%s)(.*)(%s)' % (stringA, stringB))
>>> regex.sub(r'\3\2\1', "I told John to give the bag to Tim.")
'I told Tim to give the bag to John.'
>>> regex.sub(r'\3\2\1', "John said hello to Tim.")
'Tim said hello to John.'
>>> regex.sub(r'\3\2\1', "John!h9aghagTim")
'Tim!h9aghagJohn'

答案 1 :(得分:1)

要采用的方法是使用捕获组,以便您可以将它们引用到以后

result = re.sub(r"(\{text1\}) (\{stringA\}) (\{text2\}) (\{stringB\}) (\{text3\})", r"\1 \4 \3 \2 \5", subject)

捕获组由括号()标识,你在python中通过\ x引用它们,其中x是捕获组的编号

更新1

您的示例更明显地表达您想要的内容以及您目前对正则表达式的看法。正则表达式匹配字符的模式。你想交换名字(汤姆,蒂姆,......),所以我们需要提出一个模式来匹配一个名称,这个名称只能通过完整的枚举来实现。在我的语言中,我认为有数千个名字,其中一些也用于指代对象,而不是人。要做出这种区分,你必须考虑正则表达式不能考虑的上下文。如果这有意义,请告诉我,因为如果你想继续下去,这很重要。

更新2

我怀疑你的问题是出于好奇,而不是解决现实生活中的问题。但是如果我们继续这样做会让你走得更远,但它并不完美而且不可能

正则表达式

(.*)\b(John|Tim|Jo)\b(.*)\b(John|Tim|Jo)\b

替换为

\1\4\3\2

在python中

result = re.sub(r"(?sm)(.*)\b(John|Tim|Jo)\b(.*)\b(John|Tim|Jo)\b", r"\1\4\3\2", subject)

注意正则表达式中的\ b表示匹配应该出现在字边界处。这可以防止像Johndoe这样的匹配。

同时观察上面的正则表达式将失败

  蒂姆买了乔丹的一些顶级域名,以约翰的约翰结束。