繁体   English   中英

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

[英]Regex - Replace \\n and \n in string by <br> but not \\\\n

我正在尝试用<br>替换字符串中的所有\\n\n ,但我不希望替换\\\\n

我尝试使用以下表达式使用否定的lookbehind,但它没有返回正确的结果,因为所有的"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>!'

预计 output

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

这会变魔术:

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)。

您的正则表达式具有匹配\n\n的字符 class [\\n\n] 您的后视逻辑是正确的,您只需要将角色 class 更改为不同的子模式: \\{1,2}n

请参阅此处使用的正则表达式

(?<!\\)\\{1,2}n
  • (?< \\)否定后视确保前面的不是\
  • \\{1,2}匹配\一次或两次
  • n从字面上匹配

替换: <br>

替代方案: @revo在问题下方的评论中提供的(?<?\\)\\\\ n


代码中的用法

在这里查看使用中

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))

结果: this is a sample<br>string\\\\ncontaining<br>all cases<br><br><br>

带有后视功能的正则表达式版本是最短的解决方案:

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

请参阅此 Pyhton 演示

细节

  • (?< \\)\\n - 如果紧挨当前位置的左侧有一个\符号,然后是一个\n 2-char 字符串,则匹配失败
  • \n - LF 符号。

这是一个带有来自 OP 的字符串的正则表达式演示

另一种方法是匹配并捕获要保留的\\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>

也许这会找到你想要的,而不是你可以用<br>替换:
(?<?\\)(\\)n|( < \\)(\\\\)n

上面提到的魔法和代码行在某些情况下具有相似的输出,但它没有在数据集中的选定列表中提供所需的输出,其中格式在几次迭代后发生了变化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM