【问题标题】:Regular expression to replace brackets that embrace whole entry正则表达式替换包含整个条目的括号
【发布时间】:2014-04-17 10:11:59
【问题描述】:

我有一个制表符分隔的 txt 文件。

1    (hi7 there)    my
2    (hi7)there    he3

只有当括号包含整个条目时,我才想删除括号(无论如何,我不确定条目这个词是否是描述它的正确词)

所以输出应该是

1    hi7 there    my
2    (hi7)there    he3

我知道我可以轻松找到删除所有括号的方法。但是只有当括号包含整个条目时,我才找到如何删除括号。

我可以简单地使用notepad++或python,哪个更快?

【问题讨论】:

  • 它们真的是制表符,还是只是多个空格?
  • 性能并不重要,不是吗?无论如何,既然你没有展示你的尝试,我会给你一个提示:使用积极的前瞻来检查前面是否有空格(?=\s)
  • @Robin 它们以制表符分隔。我不知道如何在 stackoverflow 帖子中放置标签。但它们确实是按标签划分的。

标签: python regex notepad++


【解决方案1】:

这个 expr 似乎可以正确处理所有可能性:

(?m)     # multiline mode
(^|\t)   # start of line of field 
\(       # (
   ([^\t]+?) # anything but a tab
\)       # )
(?=      # followed by...
   $|\t  # end of line or field
)

替换为\1\2

例子:

import re

rx = r'(?m)(^|\t)\(([^\t]+?)\)(?=$|\t)'

txt = """
1   (hi7 (the)re)   (my)
2   (hi7)there  he3
(22)    (hi7)there  he3
(22)    (hi7there)  (he3)
"""

print re.sub(rx, r'\1\2', txt)

结果:

1   hi7 (the)re my
2   (hi7)there  he3
22  (hi7)there  he3
22  hi7there    he3

【讨论】:

  • 如何在 notepad++ 中使用它以便进行测试?如果必须由python来完成,如何指定输入和输出文件名?
  • @user2604484:在 np++ 中尝试删除 (?m) 位,IIRC 默认情况下会这样做。
  • 效果很好!我很困惑,因为如果我单击“replaceall”它可以完美地工作,但如果我反复单击“replace”它会成功替换第三列。无论如何,这不是一个重要的问题。那么如果有问题的括号是“”或{}而不是(),我该怎么办?这是正确的吗?: (?m)(^|\t)\"([^\t]+?)\"(?=$|\t)
  • @user2604484:是的,应该没问题。
  • @georg 干得好。对学习正则表达式真的很感兴趣。这里是想要学习正则表达式的链接。stackoverflow.com/questions/16461680/regex-best-way-to-learn-it
【解决方案2】:

我认为这应该可行

f = open("file.txt")
for line in f:
 l = line.strip().split("    ")
 for word in l:
  if word[0] == "(" and word[-1] == ")":
   print (word[1:len(word)-1]),
  else:
   print (word),
 print

用于覆盖

import fileinput

for line in fileinput.FileInput("file.txt", inplace=1):
    l = line.strip().split("    ")
    s = ""
    for sent in l:
        if sent[0] == "(" and sent[-1] == ")":
            s += sent[1:len(sent) - 1] + "    "
        else:
            s += sent + "    "
    print s[:-1]

【讨论】:

  • @Vijay_Kumar 这行得通吗?我测试过,但文件没有任何变化。
  • 它不会更改文件,它会打印您的要求,如果您想在文件中更改具有读/写权限的打开文件并执行您想要的操作。
  • 嗨 Vijay,如何将结果覆盖到原始文件 file.txt?
  • 嗨,我添加了一些代码用于将结果覆盖到原始文件
  • 感谢您的持续帮助。但是代码只是删除了输入文件中的所有内容。输入文件是制表符分隔的 txt。并且输入文件通常有非英语,虽然我的测试输入没有非英语,但代码仍然删除了所有内容..
【解决方案3】:

你可以在python正则表达式中使用制表符\t,所以你可以这样匹配:

>>> import re
>>> re.match('^\([^\t]+\)\t.*$', '(hi7 there)\tmy')
>>> <_sre.SRE_Match object at 0x02573950>
>>> re.match('^\([^\t]+\)\t.*$', '(hi7)there\tmy')
>>>

一旦你知道如何匹配你的字符串,只有当行匹配时才容易删除括号。

【讨论】:

  • 小心,这也会匹配hi(there)
  • 不,因为^ 与行首匹配,所以左括号应该是第一个字符。在我的电脑(python v2.7)上,正则表达式与hi(there)不匹配。
  • 哎呀,你是对的,我的错。但是它会如何匹配1 \t (hi7 there) \t my呢? (为便于阅读添加了空格)
【解决方案4】:

如果真的是制表符分隔,可以替换

\t\(([^\t]*)\)\t

\t           # a tab
\(           # an opening parenthesis
(            # open the capturing group
    [^\t]*   # anything but a tab
)
\)
\t

\t\1\t

这个想法是捕获相关括号内的文本,并用反向引用\1替换它。

demo

【讨论】:

  • 如果(...) 列位于行尾的开头,这将不起作用。如果这是一个问题,请告诉我,修复很简单,但会降低正则表达式的可读性。
  • “行首行尾”是什么意思?
  • @user2604484:我的意思是在1 \t hi7 there \t (my)(为便于阅读而添加空格)中,当前的正则表达式不会用my替换(my):它不适用于第一列或最后一列.如果你想要它,你需要使用@georg的解决方案(同样的想法扩展)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多