替换位于两个特定字符串之间的文本串

19

这是我的问题:在一个包含逗号的文本变量中,我想仅删除位于两个字符串之间(实际上是[])的逗号。例如使用以下字符串:

input =  "The sun shines, that's fine [not, for, everyone] and if it rains, it Will Be better."
output = "The sun shines, that's fine [not for everyone] and if it rains, it Will Be better."
我知道如何使用.replace替换整个变量,但我无法对其中的一部分进行操作。网站上有一些相关主题,但我无法将它们应用于我的问题,例如:
4个回答

33
import re
Variable = "The sun shines, that's fine [not, for, everyone] and if it rains, it Will Be better."
Variable1 = re.sub("\[[^]]*\]", lambda x:x.group(0).replace(',',''), Variable)
首先,您需要找到需要重写的字符串部分(使用re.sub实现)。然后,重新编写这些部分。
函数var1 = re.sub("re", fun, var)的意思是:查找变量var中符合 "re"的所有子字符串; 使用函数fun处理它们; 返回结果; 结果将保存到var1变量中。
正则表达式"[[^]]*]"的意思是:查找以[起始(在re中为\[),除]之外的任何内容(在re中为[^]]*),并以]结束(在re中为\])的子字符串。
对于每个找到的匹配项,运行一个将该匹配项转换为新值的函数。该函数如下:
lambda x: group(0).replace(',', '')

这意味着:获取到的字符串(group(0))将会被替换,将其中的,替换为空字符''(也就是移除掉,),然后返回结果。


@user1453786: 非常尊重地说, @Qtax 的回答更好。函数式的 sub 是一种很有用的技术,但在这种情况下显然是过度的。 - georg
@thg435:不,它不是。因为它不能处理不平衡的括号,例如:"not, for, everyone] and if it rains, it Will [a,c],",这个表达式在Qtax中只检查了后面部分,这是错误的。当然可以添加回顾断言,但那就不再那么简单了。 - Igor Chubin
1
伟大的答案需要出色的解释。 - trinaldi

4
您可以使用这样的表达式来匹配它们(如果括号是平衡的):
,(?=[^][]*\])

使用类似以下的东西:

re.sub(r",(?=[^][]*\])", "", str)

我喜欢你的答案,它非常干净有效,但我认为它有一个缺点。我认为这对于不平衡的括号是行不通的。你只检查表达式的结尾部分。使用前瞻/后顾断言来解决这个任务将会非常棒,但我不确定那样做是否像现在这样优雅。 - Igor Chubin

0
这是一个非正则表达式的方法。您可以将 [] 定界符替换为 [//],然后在 / 定界符上进行 split。然后,拆分列表中的每个 奇数 字符串都需要进行 逗号 删除,可以在列表理解中重建字符串时完成:
>>> Variable = "The sun shines, that's fine [not, for, everyone] and if it rains,
                it Will Be better."
>>> chunks = Variable.replace('[','[/').replace(']','/]').split('/')
>>> ''.join(sen.replace(',','') if i%2 else sen for i, sen in enumerate(chunks))
"The sun shines, that's fine [not for everyone] and if it rains, it Will Be 
 better."

-1

如果您不喜欢学习正则表达式(请参见本页面上的其他回答),您可以使用分区命令。

sentence = "the quick, brown [fox, jumped , over] the lazy dog"
left, bracket, rest = sentence.partition("[")
block, bracket, right = rest.partition("]")

“block”现在是括号里的字符串部分,“left”是左括号左边的内容,“right”是左括号右边的内容。
然后您可以使用以下方法恢复完整句子:
new_sentence = left + "[" + block.replace(",","") + "]" + right
print new_sentence # the quick, brown [fox jumped over] the lazy dog

如果你有多个块,你可以将它们全部放在一个for循环中,在每一步应用"right"的分区命令。
或者你可以学习正则表达式!从长远来看,这将是值得的。

当字符串中有多个“特殊”部分时(例如:“a,b [c,d] e,f [g,e] h,i”),此方法将无法工作。 - Igor Chubin
不要将变量命名为 string,这会让期望它是 Python 标准库中的 string 模块 的开发人员感到困惑。 - Martijn Pieters
此外,为什么不在这里使用.split('[', 1),反正你要丢掉括号。第二个.partition调用应该在rest上进行,而不是在string上进行,所以这段代码根本无法工作。string最终变成了"the quick, brown [the quick brown [fox jumped over] the lazy dog" - Martijn Pieters
已做出修改,删除了打字错误并更改了变量名称。感谢您的反馈。 - Pascal Bugnion

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