正则表达式 - 将字符串中的 \\n 和 \n 替换为 <br>,但不替换 \\\\n

9
我正在尝试将字符串中的所有\\n\n替换为<br>,但我不希望替换\\\\n。我尝试使用负回顾后发表达式,但它没有返回正确的结果,因为所有的"n""\"都被替换了。
import re
string = "this is a sample\\nstring\\\\ncontaining\nall cases\n\\n\n!"
re.sub(r"(?<!\\)([\\n\n]+)", r"<br>", string)
>>'this is a sample<br>stri<br>g<br>co<br>tai<br>i<br>g<br>all cases<br>!'

期望输出

"this is a sample<br>string\\\\ncontaining<br>all cases<br><br><br>!"

等一下,你想用1个 <br> 替换多个连续的\n和LF符号吗? - Wiktor Stribiżew
好的观点!多个连续的\n将被替换为多个连续的<br>。 - Below the Radar
我认为你的示例可能没有按照你想象的那样工作。如果你打印原始字符串,\n会显示在同一行上,就像sample\nstring一样。 - Michael Robellard
4个回答

4
这将起到魔法般的作用:
re.sub(r"(?<!\\)\\n|\n", "<br>", string)

注意:它将替换换行符(“\n”)和转义的换行符(“\n”或r“\n”)。不会转义“\\n”(或r“\n”)。反斜杠+换行符(“\\\n”)变成“\\<br>”。
也许,你真正想要的是:
re.sub(r"(?<!\\)(\\\\)*\\n|\n", "\1<br>", string)

这将替换所有的换行符和所有转义的n(r"\n")。r"\\n"不会被替换。r"\\\n"再次被替换(转义反斜杠+转义n)。


我认为最后一个应该是 re.sub(r"(?<!\\)((?:\\\\)*)\\n|\n", r"\1<br>", string)。有趣的是,它只匹配未转义的\n +1。 - Wiktor Stribiżew

3
你的正则表达式中有字符类[\\n\n],它匹配\n\n。你的回顾逻辑是正确的,你只需要将字符类更改为不同的子模式:\\{1,2}n在此处查看使用的正则表达式
(?<!\\)\\{1,2}n
  • (?<!\\)负向预查,确保前面不是\
  • \\{1,2}匹配\一次或两次
  • n匹配字母n

替换为:<br>

可选方案为:(?<!\\)\\\\?n,由问题下方评论中的@revo提供


代码中的使用方法

在此处查看使用情况

import re

r = re.compile(r"(?<!\\)\\{1,2}n")
s = r"this is a sample\\nstring\\\\ncontaining\nall cases\n\\n\n!"
print(r.sub("<br>", s, 0))

结果: 这是一个包含所有情况的示例<br>字符串\\\\n


这里的“\\”代表换行符。

1
@BelowtheRadar 请查看链接。你可能没有在输入字符串之前加上 r - ctwheels
虽然量词似乎更易读,但我喜欢 (?<!\\)\\\\?n。你得到了我的 +1。 - revo
我接受了Wiktor Stribiżew的答案,因为它在使用之前不需要转义字符串,但是你的解决方案也很好。+1 - Below the Radar
@WiktorStribiżew,非常抱歉,我没有在您的回答中看到那个。我会像您一样删除它,因为您先发布了回答。 - ctwheels
1
在你的情况下,r'%s' % str 不起作用吗?@BelowtheRadar - revo
显示剩余6条评论

0

也许这个可以找到你想要的,然后你可以用<br>替换:
(?<!\\)(\\)n|(?<!\\)(\\\\)n


0

使用反向引用的正则表达式版本是最短的解决方案:

import re
s = "this is a sample\\nstring\\\\ncontaining\nall cases and one more\\n\nadded"
print(re.sub(r"(?<!\\)\\n|\n", "<br>", s))
## => this is a sample<br>string\\ncontaining<br>all cases and one more<br><br>added

请查看这个Python演示

详情

  • (?<!\\)\\n - 负向先行断言,如果当前位置左侧紧挨着一个\符号和一个\n的2个字符字符串,则匹配失败
  • \n - 换行符。

这里有一个正则表达式演示,使用了原始问题中的字符串。

另一种方法是匹配并捕获要保留的\\n,然后匹配不捕获的\n和LF,并使用lambda表达式作为替换参数来实现自定义替换逻辑:

import re
s = "this is a sample\\nstring\\\\ncontaining\nall cases and one more\\n\nadded"
print(re.sub(r"(\\\\n)|\\n|\n", lambda x: r"<br>" if not x.group(1) else x.group(), s))
# => this is a sample<br>string\\ncontaining<br>all cases and one more<br><br>added

请看Python演示

在这里,(\\\\n)|\\n|\n匹配并捕获\\n(\\\\n)(将重新插入到结果中(if not x.group(1) else x.group() = 如果组1匹配,则用其内容替换),或匹配\n(使用\\n)或 LF(使用\n)以将其替换为<br>


@BelowtheRadar 请查看此处发布的r"(?<!\\)\\n|\n"。 它可能是更好的解决方案,因为 (?<!\\)(?:\\n|\n) 不会匹配s="abc\\\nhere"中的LF。 如果您需要在该字符串中替换\n,请接受dercolamann的解决方案。 尽管如此,我的第二个带有lambda的解决方案仍适用于这个示例。 - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接