【问题标题】:regex: find all asterisks without prepended backslashes正则表达式:查找所有不带反斜杠的星号
【发布时间】:2016-08-06 06:05:09
【问题描述】:

我正在构建一个将*asterisks* 转换为<b>bold tags</b> 的正则表达式,作为Markdown 的更简单版本。正则表达式如下所示:

markdown = '\*(?P<name>.+)\*'
bold = '<b>\g<name></b>'
text = 'abcdef *bold* ghijkl'
print(re.sub(markdown, bold, text))

>>> abcdef <b>bold</b> ghijkl

现在我需要忽略转义的星号\*,在这里我遇到了两个问题:

问题 1

当我尝试将转义符号指定为 \\

markdown = '[^\\]\*(?P<name>.+)[^\\]\*'

我收到一个 Python 错误:

sre_constants.error: unexpected end of regular expression

所以某处存在语法错误,似乎无法修复。

问题 2

假设我想忽略前置符号 A(不是反斜杠)。我的正则表达式在这里起作用:

markdown = '[^A]\*(?P<name>.+)[^A]\*'
bold = '<b>\g<name></b>'
text = 'abcdef A*bold* ghijkl'
print(re.sub(markdown, bold, text))

>>> abcdef A*bold* ghijkl

但如果我的行中没有前置A,则文本中的一些有价值的符号会被正则表达式消耗:

text = 'abcdef *bold* ghijkl'
print(re.sub(markdown, bold, text))

>>> abcdef<b>bol</b> ghijkl

注意第一个空格 和字母d 已经消失了。

我该如何处理这两个问题?

【问题讨论】:

  • 正则表达式并非在所有情况下都有效,请编写一个简单的解析器。

标签: python regex


【解决方案1】:

问题 1a:语法错误

它不起作用,因为您还必须转义反斜杠。

markdown = '[^\\\\]\*(?P<name>.+)[^\\\\]\*'

或者使用r'' 定义一个原始字符串。

markdown = r'[^\\]\*(?P<name>.+)[^\\]\*'

问题 1b:解决方案

我的建议:不要试图用一个正则表达式来解决它。

  1. 自定义转义有问题的字符。
  2. 运行正常的正则表达式。
  3. 撤消自定义转义。

代码:

my_escapes = {
    '%backslash-escaped%': '\\\\',
    '%bold-escaped%': '\\*',
}

text = r'text \*not-bold text2 *bold* text3 \\*bold* text4 \\\*not-bold text5 \\\\*bold* text6'
text = re.sub('\\\\\\\\', '%backslash-escaped%', text)  # escape escaped escape characters
text = re.sub('\\\\\*', '%bold-escaped%', text)  # escape escaped bold characters
text = re.sub('(?<!\\\\)\*(?P<bold>[^\*\\\\]+)\*', '<b>\g<bold></b>', text)  # add bold parts

# undo all escapes
for key, value in my_escapes.iteritems():
    text = text.replace(key, value)

print text

>>> text \*not-bold text2 <b>bold</b> text3 \\<b>bold</b> text4 \\\*not-bold text5 \\\\<b>bold</b> text6

问题2:字符消失

它们消失了,因为您已匹配但未重新插入它们。为此,将它们包装在组中(这里命名为组)和 在替换字符串中插入组。

markdown = '(?P<first_char>[^A])\*(?P<name>.+)(?P<sec_char>[^A])\*'
bold = '\g<first_char><b>\g<name></b>\g<sec_char>'

或者使用lookarounds,它们会匹配但不消耗字符。

markdown = '(?<!A)\*(?P<name>.+)(?!A)\*'
bold = '<b>\g<name></b>'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    相关资源
    最近更新 更多