Python 正则表达式:如何匹配连续行中的每行换行?

0 投票
4 回答
914 浏览
提问于 2025-04-30 23:09

我有以下文本:

s = """
{
    "list-of-stuff": "{
        (analog-input, 1), (analog-input, 2), (analog-input, 3),
        (analog-input, 4), (analog-input, 5), (analog-input, 6),
        (analog-input, 7), (analog-input, 8), (analog-input, 9),
        (analog-input, 10), (analog-input, 11), (analog-input, 12),
        (analog-input, 13), (analog-input, 14), (analog-input, 15),
        (analog-input, 16), (analog-input, 17), (analog-input, 18),
        (analog-input, 19), (analog-input, 20), (analog-input, 21),
        (analog-input, 22), (analog-input, 23), (analog-input, 24),
        (analog-input, 25), (analog-input, 26), (analog-input, 27),
        (analog-input, 28), (analog-input, 29), (analog-input, 30),
        (analog-input, 31), (analog-input, 32), (analog-output, 1)
    }"
},
{
    "identifier": "(analog-input, 0)",
    "name": "AI 00",
    "type": "analog-input",
    "value": "?",
    "description": "Temp",
    "flags": "{false,false,false}",
    "state": "normal",
    "service": "FALSE",
    "reliability": "?"
}
"""

我想把第二个字符串中的所有换行符({...})从 \n 转换成 \\n。(我想让这个 JSON 更易读)我该怎么做呢?

这是我尝试过的方法:

s = re.sub(r'^[^"}]+,(\s*)\n', r'\1,\2\\n', s, flags=re.MULTILINE)
s = re.sub(r'^[^"}]+,(\s*)$', r'\1,\2\\n', s, flags=re.MULTILINE)

可惜,这些方法都不行。我得到的结果最接近的是:

s = """
{
    "list-of-stuff": "{
        (analog-input, 1), (analog-input, 2), (analog-input, 3),
        (analog-input, 4), (analog-input, 5), (analog-input, 6),
        (analog-input, 7), (analog-input, 8), (analog-input, 9),
        (analog-input, 10), (analog-input, 11), (analog-input, 12),
        (analog-input, 13), (analog-input, 14), (analog-input, 15),
        (analog-input, 16), (analog-input, 17), (analog-input, 18),
        (analog-input, 19), (analog-input, 20), (analog-input, 21),
        (analog-input, 22), (analog-input, 23), (analog-input, 24),
        (analog-input, 25), (analog-input, 26), (analog-input, 27),
        (analog-input, 28), (analog-input, 29), (analog-input, 30),\n        (analog-input, 31), (analog-input, 32), (analog-output, 1)
    }"
},
{
    "identifier": "(analog-input, 0)",
    "name": "AI 00",
    "type": "analog-input",
    "value": "?",
    "description": "Temp",
    "flags": "{false,false,false}",
    "state": "normal",
    "service": "FALSE",
    "reliability": "?"
}
"""

看起来 re.MULTILINE 模式会在所有连续的行上进行匹配。但是,我需要逐行匹配。可惜的是,我需要 re.MULTILINE,否则 \n 就无法匹配。有什么建议吗?

更新

我更新了我的问题,以更好地反映我的情况。这个字符串还有其他属性需要满足,这在我的正则表达式中有体现。例如,我需要排除 }, 这样的匹配,以及其他不在 JSON 字符串中的行。因此,我不能简单地把所有的 \n 替换成 \\n

抱歉让你们困惑了。

暂无标签

4 个回答

0

你需要使用多行字符串,像这样:

s= '''
"list-of-stuff": "{ 
(analog-input, 1), (analog-input, 2), (analog-input, 3), 
(analog-input, 4), (analog-input, 5), (analog-input, 6), 
(analog-input, 7), (analog-input, 8), (analog-input, 9), 
(analog-input, 10), (analog-input, 11), (analog-input, 12), 
(analog-input, 13), (analog-input, 14), (analog-input, 15), 
(analog-input, 16), (analog-input, 17), (analog-input, 18), 
(analog-input, 19), (analog-input, 20), (analog-input, 21), 
(analog-input, 22), (analog-input, 23), (analog-input, 24), 
(analog-input, 25), (analog-input, 26), (analog-input, 27), 
(analog-input, 28), (analog-input, 29), (analog-input, 30), 
(analog-input, 31), (analog-input, 32), (analog-output, 1)
}"'''

s.replace('\n','\\n')

现在替换功能就可以正常工作了

0

幸运的是,我们不需要复杂的正则表达式来处理一些内容,使其成为有效的JSON格式。Python的json模块可以帮你完成这个工作,特别是json.dumps()这个函数。我不会用你给的例子,因为它不是有效的Python代码,你的多行字符串没有使用三重引号,也没有续行符。

>>> import json
>>> x = "foo\nbar"
>>> json.dumps(x)
'"foo\\nbar"'

针对你的具体问题,我觉得用re.sub("\n","\\\\n", your_text)这个方法就可以了:

>>> import re
>>> y = "foo\nbar\njaz"
>>> re.sub("\n","\\\\n",y)
'foo\\nbar\\njaz'
3

ErlVolton解决方案最适合你想要做的事情。不过,如果你还是想用字符串处理或者正则表达式来实现这个功能,你可以简单地这样做:

s = s.replace('\n','\\n')
4

这里提到的MULTILINE方法其实不是解决这个问题的正确方式;问题本身更简单,解决方案也更简单。

在正则表达式中,默认情况下,重复匹配是贪婪的。这意味着像[^"}]+这样的表达式会尽可能多地匹配字符,只要还能让其他部分的模式匹配成功。在你的输入中,最后一个\n会和模式中的\n匹配,而中间的\n则会作为[^"}]+的一部分匹配。

不过,你可以通过使用+?来让它变得不那么贪婪,这样它就会尽量少匹配字符,同时还能让其他部分的模式匹配成功。这样,输入中的第一个\n就会和模式中的\n匹配,每一行就会被当作一个单独的匹配。

^[^"}]+?,(\s*)$

正则表达式可视化

Debuggex演示

撰写回答