2

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

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

where{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=约翰,B=蒂姆):

(1) 这个:

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

改成这样:

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

(2) 这:

“约翰向蒂姆问好。”

改成这样:

“蒂姆向约翰问好。”

(3) 这个:

“约翰!h9aghagTim”

改成这样:

“蒂姆!h9aghagJohn”

4

2 回答 2

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

stringA和替换stringB为您感兴趣的子字符串,请注意您可能需要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'
于 2012-05-29T21:43:26.917 回答
1

采用的方法是使用捕获组,以便您以后可以参考它们

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

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

更新 1

您的示例使您更清楚您想要什么以及您目前对正则表达式的看法。正则表达式匹配字符模式。你想交换名字(Tom,Tim,...)所以我们需要想出一个模式来匹配一个只有通过完整枚举才有可能的名字。在我的语言中,(我认为)有数千个名字,其中一些也用于指代对象而不是人。要做出这种区分,您必须考虑正则表达式不能考虑的上下文。让我知道这是否有意义,因为如果您想更进一步,这很重要。

更新 2

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

正则表达式

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

用。。。来代替

\1\4\3\2

在蟒蛇

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

请注意正则表达式中的 \b ,它表明匹配应该发生在单词边界处。这可以防止像 Johndoe 这样的比赛。

还要注意上面的正则表达式对于句子会失败

Tim 从 John 那里购买了一些以 Jo 结尾的 Jordan 顶级域名

于 2012-05-29T21:42:14.190 回答