【问题标题】:Regex to match special list items正则表达式匹配特殊列表项
【发布时间】:2016-01-18 14:44:39
【问题描述】:

我有奇怪的项目列表和类似这样的列表,| 作为分隔符,[[ ]] 作为括号。它看起来像这样:

| item1 | item2 | item3 | Ulist1[[ | item4 | item5 | Ulist2[[ | item6 | item7 ]] | item8 ]] | item9 | list3[[ | item10 | item11 | item12 ]] | item13 | item14

我想使用 RegEx 匹配名为 Ulist* 的列表中的项目(项目 4-8),并将它们替换为 Uitem*。结果应如下所示:

| item1 | item2 | item3 | Ulist1[[ | Uitem4 | Uitem5 | Ulist2[[ | Uitem6 | Uitem7 ]] | Uitem8 ]] | item9 | list3[[ | item10 | item11 | item12 ]] | item13 | item14

我尝试了我所知道的关于 RegEx 的几乎所有内容,但如果 Ulist 中的每个项目,我还没有找到任何匹配的 RegEx。我目前的正则表达式:

/Ulist(\d+)\[\[(\s*(\|\s*[^\s\|]*)*\s*)*\]\]/i

怎么了?我是 RegEx 的初学者。

它在 Python 2.7 中,具体我的代码是:

    def fixDirtyLists(self, text):
        text = textlib.replaceExcept(text, r'Ulist(\d+)\[\[(\s*(\|\s*[^\s\|]*)*\s*)*\]\]', r'Ulist\1[[ U\3 ]]', '', site=self.site)
        return text

text 得到那个奇怪的列表,textlib 用 RegEx 替换 RegEx。一点都不复杂。

【问题讨论】:

  • 你之前已经问过这个问题,它被删除了。怎么又问了?
  • 请添加您的代码,在哪里使用此 RE
  • 我从来没有在这里问过。添加了一段代码并更新了问题
  • 你尝试过 PyPi 正则表达式模块吗?它支持递归。

标签: python regex python-2.7


【解决方案1】:

如果您安装PyPi regex module(使用Python 2.7.9+,在\Python27\Scripts\ 文件夹中只需pip install regex 即可完成),您将能够匹配嵌套的方括号。您可以匹配您需要的字符串,仅在这些子字符串中将item 替换为Uitem

模式(参见demo,注意 PyPi 正则表达式递归类似于 PCRE):

(Ulist\d+)(\[\[(?>[^][]|](?!])|\[(?!\[)|(?2))*]])
^-Group1-^^-----------Group2--------------------^

简短的解释:(Ulist\d+) 是第 1 组,它匹配文字词 Ulist,后跟 1 个或多个数字,后跟 (\[\[(?>[^][]|](?!])|\[(?!\[)|(?2))*]]),匹配以 [[ 开头的子字符串,直到对应的 ]]

还有 Python 代码:

>>> import regex
>>> s = "| item1 | item2 | item3 | Ulist1[[ | item4 | item5 | Ulist2[[ | item6 | item7 ]] | item8 ]] | item9 | list3[[ | item10 | item11 | item12 ]] | item13 | item14"
>>> pat = r'(Ulist\d+)(\[\[(?>[^][]|](?!])|\[(?!\[)|(?2))*]])'
>>> res = regex.sub(pat, lambda m: m.group(1) + m.group(2).replace("item", "Uitem"), s)
>>> print(res)
| item1 | item2 | item3 | Ulist1[[ | Uitem4 | Uitem5 | Ulist2[[ | Uitem6 | Uitem7 ]] | Uitem8 ]] | item9 | list3[[ | item10 | item11 | item12 ]] | item13 | item14

为避免在Ulist 中修改lists,请使用

def repl(m):
    return "".join([x.replace("item", "Uitem") if not x.startswith("list") else x for x in regex.split(r'\blist\d*\[{2}[^\]]*(?:](?!])[^\]]*)*]]', m.group(0))])

并将regex.sub 替换为

res = regex.sub(pat, repl, s)

【讨论】:

  • 谢谢你,我会尝试,我会写,如果它对我有用与否,但它看起来像一个很好的解决方案
  • Ulist 内部有list 时,就会出现问题。我不想将该列表中的项目更改为 Uitems,因为它不是 Ulist。你知道如何解决这个问题吗?
  • 在回调方法中应该更容易处理。我需要一些时间来检查。
  • 您可以使用 regex.sub(regex_pattern, replacement, input)
  • x.replace(old, new) 仅使用常规字符串替换。使用re/regex时,需要(re or regex).sub(regex_searching_for_old, pattern_replacement_with_new, x)。我认为 pastebin 的代码应该可以工作。
猜你喜欢
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多