【问题标题】:Remove notes with brackets, regex删除带括号的注释,正则表达式
【发布时间】:2022-01-07 17:16:46
【问题描述】:

所以,我有一个 300 多页的文档,我想删除我写的所有注释,这些注释包含在“[(”和“)]”中。因为我有时也会嵌套多个音符,“[(blah [(blah [(blah)])] )]”,我需要确保我不只是删除“[(blah [(blah [(blah)]”) .

所以,要做到这一点,我不确定什么是最有效的......这是一项艰巨的工作。我想到的是,我可以检查是否有两个连续的“[(”,它们之间有一个“。*”,只需删除“[(...)]”的简单案例。我希望不过,还有比这更好的方法。

我认为我使用的两个正则表达式代码类似于 "/(?和 "/(?![\s\S][[(][\s\S][[(]).*/gi"。类似的东西? 对不起,我还在努力弄清楚这些事情。

另外,我可以编写一个 python 程序来打开 OpenOffice (odt) 文件并对其进行编辑吗? “open(r'C:\Users\Blah\Documents\Blah.odt', 'rw').read()” 也适用,对吧?

【问题讨论】:

  • 这能回答你的问题吗? Regexp to remove nested parenthesis
  • 嵌套层数可以多于两层吗(这里’[(blah [(blah [(blah)])] )]’可以认为是两层嵌套)?
  • 可以存在任意数量的嵌套级别。我有时会在笔记中写几个笔记,哈哈。
  • @Woodford,您引用的问题的两个答案不使用正则表达式(尽管一个使用简单的表达式作为计算的一部分)。
  • 我建议您编辑您的问题以包含该信息,然后我们删除我们的 cmets。

标签: python regex loops


【解决方案1】:

或者,您也可以使用pyparsing

import pyparsing as pp

pattern = pp.ZeroOrMore(pp.Regex(r'.*?(?=\[\()') + pp.Suppress(pp.nested_expr('[(', ')]'))) + pp.Regex(r'.*')
pattern = pattern.leave_whitespace()

txt = ''
result = ''.join(pattern.parse_string(txt))
assert result == ''

txt = 'blah'
result = ''.join(pattern.parse_string(txt))
assert result == 'blah'

txt = 'blah\nblah'
result = ''.join(pattern.parse_string(txt))
assert result == 'blah'

txt = '[(blah [(blah [(blah)])] )]'
result = ''.join(pattern.parse_string(txt))
assert result == ''

txt = ' blah [] blah () blah [( blah [] blah () )] blah [[]] blah (()) blah ([]) blah '
result = ''.join(pattern.parse_string(txt))
assert result == ' blah [] blah () blah  blah [[]] blah (()) blah ([]) blah '

txt = 'a[(b[(c)])]d[()]e[(f[(g[(h)]i[(j)])]k[(l[(m)])])n[(o)])]p[(q[(r)]s)]t[(u[(v[(w)]x[(y)]z)])]!'
result = ''.join(pattern.parse_string(txt))
assert result == 'adept!'

* pyparsing可以由pip install pyparsing安装

注意:

如果[()] 中的一对括号被破坏(例如a[(b[(c)]a[(b)]c)] 等),则会获得意外结果或引发IndexError。所以要小心使用。 (见:Python extract string in a phrase

【讨论】:

  • 很高兴看到您很好地利用了 pyparsing!对于这样的代码转换器,您可以将其编写为 pp.nested_expr('[(', ')]')).suppress().transform_string(txt)transform_string 接受一个 str 并返回一个解析/转换文本的 str。对于parse_string 的其他替代方案,另请查看scan_stringsearch_string
  • 我检查了你的方法,我说“哇”。这比我的方法要酷得多!我必须更深入地学习pyparsing。感谢您分享很酷的技术:)
【解决方案2】:

以这种方式检查:

a = '[(blah [(blah [(blah)])] )]'

x = re.compile(r'([\[])(.*?)([\]])')
remove_text = re.sub(x, r'', a)

【讨论】:

  • 先生,您的方法看起来不错,简洁,但我的知识并不完善,所以请让我澄清一两点。我认为“*”表示“0+”次出现,对吧?问号后面...将其标记为“可选”?你把它放在那里以防我写了'[()]'这样的东西对吗?我也想捕捉空格、换行符等,只是碰巧我有它们......所以不是“*”,而是“[\s\S]”会更好吗?感谢您的帮助!
  • 您需要更多地使用正则表达式来了解这里发生的原因和方式。这里有一些有用的链接:stackoverflow.com/questions/3075130/…developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…developpaper.com/analyze-the-meaning-of-in-regular-expression
  • 啊!我觉得我懂了。通过让它“不情愿”,你会抓住第一个“)]”,对吗?然后会返回“[(blah [(blah [(blah)]”)?正如链接所解释的那样,这里的贪婪选择会更好,因为我的主要目标是删除所有笔记?那将选择“[(blah [ (blah [(blah)])] )]",因为贪婪从最后开始工作并回溯匹配。
【解决方案3】:

一种方法是重复删除(用空字符串替换匹配项)此类不包含子句的子句,直到不再进行替换为止。如果最大级别数是n,这将需要n+1 迭代。要匹配的正则表达式如下:

\[\((?:(?!\[\().)*?\)\]

Demo


考虑字符串:

begin [(Mary [(had [(a )]lil' [(lamb [(whose [(fleece )])])])])]was [(white [( as )])]snow
      1      2     3    3     3      4       5         5 4 3 2 1    1       2      2 1

如图所示,它有五个嵌套级别。第一次替换后我们得到:

begin [(Mary [(had lil' [(lamb [(whose )])])])]was [(white )]snow
      1      2          3      4        4 3 2 1    1        1

第二次替换后:

begin [(Mary [(had lil' [(lamb )])])]was snow
      1      2          3       3 2 1

第三次替换后:

begin [(Mary [(had lil' )])]was snow
      1      2           2 1

第四次替换后:

begin [(Mary )]was snow
      1       1

第五次替换后:

begin was snow

下次尝试替换后:

begin was snow

由于在最后一步没有进行替换,所以我们完成了。


正则表达式可以分解如下。

\[\(        # match '[('
(?:         # begin non-capture group
  (?!\[\()  # negative lookahead asserts that next to chars are not '[('
  .         # match any char
)*?         # end non-capture group and execute zero or more times lazily
\)\]        # match ')]'

正则表达式采用了一种称为tempered greedy token solution的技术。

【讨论】:

  • 太棒了,先生!一个人如何学习达到这个水平?从事许多项目,或通过书籍...?但如果我可能会问,因为我想考虑可能的换行符等,我假设我可以替换“。”用“[\s\S]”,对吧?
  • 错误:import sys import re from odf.opendocument import load from odf import text, teletype infile = load(r'C:\Users\Iainc\Documents\Blah Blah.odt') for item in infile.getElementsByType(text.P): s = teletype.extractText(item) m = re.sub(r'[((?:(?![().)*?)]', '', s);如果 m != s: new_item = text.P() new_item.setAttribute('stylename', item.getAttribute('stylename')) new_item.addText(m) item.parentNode.insertBefore(new_item, item) item.parentNode。 removeChild(item) infile.save('C:\Users\Iainc\Documents\Blah Blah.odt 2')
  • 错误如下: infile.save(r'C:\Users\Iainc\Documents\The Seventh Story 2.odt') File "", line 10 infile.save(r 'C:\Users\Iainc\Documents\The Seventh Story 2.odt') ^^^^^^ SyntaxError: invalid syntax 到底是什么问题......?就我所见,代码很好......(哦,当然,当我粘贴上面的代码时,它似乎从正则表达式中删除了一些东西,但实际上它应该是一样的。 )
  • 关于您的第一条评论,是的,您可以使用[\s\S](或[\w\W]),但您只需设置单行标志即可获得相同的结果.至于如何熟练使用正则表达式,这与人们熟练掌握任何计算机语言的方式没有什么不同。在我自己的情况下,在大多数情况下,我只是通过在这个论坛上闲逛来获得它。不过,我不是专家。正则表达式有一个神秘之处,但这主要是由于不熟悉的符号。基础知识实际上非常简单。
  • 我只知道一点点 Python,我无法帮助您解决您遇到的错误。我建议您将代码发布在 tio.run 之类的网站上,然后发布带有代码链接的评论,并请读者帮助您更正它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 2018-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
相关资源
最近更新 更多