Python 正则表达式:如何匹配连续行中的每行换行?
我有以下文本:
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 个回答
你需要使用多行字符串,像这样:
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')
现在替换功能就可以正常工作了
幸运的是,我们不需要复杂的正则表达式来处理一些内容,使其成为有效的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'
ErlVolton解决方案最适合你想要做的事情。不过,如果你还是想用字符串处理或者正则表达式来实现这个功能,你可以简单地这样做:
s = s.replace('\n','\\n')
这里提到的MULTILINE方法其实不是解决这个问题的正确方式;问题本身更简单,解决方案也更简单。
在正则表达式中,默认情况下,重复匹配是贪婪的。这意味着像[^"}]+
这样的表达式会尽可能多地匹配字符,只要还能让其他部分的模式匹配成功。在你的输入中,最后一个\n
会和模式中的\n
匹配,而中间的\n
则会作为[^"}]+
的一部分匹配。
不过,你可以通过使用+?
来让它变得不那么贪婪,这样它就会尽量少匹配字符,同时还能让其他部分的模式匹配成功。这样,输入中的第一个\n
就会和模式中的\n
匹配,每一行就会被当作一个单独的匹配。
^[^"}]+?,(\s*)$