使用python正则表达式转义无效降价

Son*_*ars 5 regex string markdown replace python-3.x

我一直在尝试编写一些 python 来转义“无效”降价字符串。

这是用于需要使用 \ 转义未使用的降价字符的 python 库 (python-telegram-bot)。

我的目标是匹配单独的*, _,`字符以及无效的超链接 - 例如,如果没有提供链接,并转义它们。

我正在寻找的一个例子是:

*hello*很好,不应该改变,而hello*会变成hello\*. 最重要的是,如果值是嵌套的,它们不应该被转义——例如_hello*_应该保持不变。

我的想法是先匹配所有双打,然后替换任何剩余的孤独字符。我使用 re.finditer() 管理了一个粗略的版本:

 def parser(txt):
   match_md = r'(\*)(.+?)(\*)|(\_)(.+?)(\_)|(`)(.+?)(`)|(\[.+?\])(\(.+?\))|(?P<astx>\*)|(?P<bctck>`)|(?P<undes>_)|(?P<sqbrkt>\[)'
   for e in re.finditer(match_md, txt):
     if e.group('astx') or e.group('bctck') or e.group('undes') or e.group('sqbrkt'):
       txt = txt[:e.start()] + '\\' + txt[e.start():]
   return txt

note: regex was written to match *text*, _text_, `text`, [text](url), and then single *, _, `, [, knowing the last groups
Run Code Online (Sandbox Code Playgroud)

但这里的问题当然是当您插入更多字符时偏移量会发生变化,因此一切都会发生变化。肯定有比添加偏移计数器更好的方法吗?

我尝试使用 re.sub(),但我无法找到如何替换特定组,或者有幸(?:)“不匹配”有效降价。

这是我的 re.sub 尝试:

def test(txt):
  match_md = r'(?:(\*)(.+?)(\*))|' \
             '(?:(\_)(.+?)(\_))|' \
             '(?:(`)(.+?)(`))|' \
             '(?:(\[.+?\])(\(.+?\)))|' \
             '(\*)|' \
             '(`)|' \
             '(_)|' \
             '(\[)'
  return re.sub(match_md, "\\\\\g<0>", txt)
Run Code Online (Sandbox Code Playgroud)

这只是在每个匹配项前面加上一个反斜杠(这是意料之中的,但我希望 ?: 会阻止它们被匹配。)

如果 \ 已经在字符串中也被转义,那么它们就不会干扰当前的降价 - 这可能是错误的来源,因为图书馆会将其视为已转义,导致它将其余部分视为无效的。

提前致谢!

yac*_*acc 1

您可能正在寻找这样的正则表达式:

def test(txt):
  match_md = r'((([_*]).+?\3[^_*]*)*)([_*])'
  return re.sub(match_md, "\g<1>\\\\\g<4>", txt)
Run Code Online (Sandbox Code Playgroud)

*请注意,为了清楚起见,我只是为和制作了一个示例_。您可以轻松扩展括号中的列表[]。现在我们就来看看这个事情。

这个想法是处理看起来像*foo_*_bar*_后面跟着不包含任何特殊字符的文本的字符串。匹配此类字符串的正则表达式是([_*]).+?\1[^_*]*:我们匹配一个开始分隔符,将其保存在 \1 中,然后沿着该行继续前进,直到看到相同的分隔符(现在结束)。然后我们吃掉后面不包含任何分隔符的任何东西。

现在,只要不再有分隔字符串,我们就希望这样做,这是通过(([_*]).+?\2[^_*]*)*. 现在右侧剩下的,如果有的话,是一个孤立的特殊情况,这就是我们需要掩盖的。比赛结束后,我们进行以下子比赛:

  • g<0> : 整场比赛
  • g<1> :子匹配((([_*]).+?\3[^_*]*)*)
  • g<2> :子匹配(([_*]).+?\3[^_*]*)
  • g<3> :子匹配([_*])(因此\3上面)
  • ([_*])g<4> :(要屏蔽的)的子匹配

现在剩下的就是找到一种方法来处理无效的超链接,这是另一个主题。

更新:
不幸的是,这个解决方案掩盖了有效的降价,例如*hello*(=> \*hello\*)。解决此问题的解决方法是在行尾添加一个特殊字符,并在替换完成后删除屏蔽的特殊字符。OP 可能正在寻找更好的解决方案。