我有一个看起来像这样的字符串:
**** SOURCE#24 ****
[1] Source Location [Local/Remote] : Remote
Remote Host Name : PNQ
User Name : foo
[2] Source directory : HDPGWRF
[3] Directory poll interval : 30
[4] File name format : ACR_FILEFORMAT
[5] Delete files from source : y
**** SOURCE#25 ****
[1] Source Location [Local/Remote] : Remote
Remote Host Name : PNR
User Name : foo
[2] Source directory : HDPGWRF
[3] Directory poll interval : 30
[4] File name format : ACR_FILEFORMAT
[5] Delete files from source : y
**** SOURCE#26 ****
etc.....
我想要一个捕获组,根据远程主机名(例如 PNR 或 PNQ)捕获“[1]”之后直到以 [5] 开头的行末尾的所有内容。因此,所选名称周围只有 [1] 到 [5] 行。
我一直在尝试向前看和向后看,但就是无法弄清楚这一点。看起来后视是贪婪的,所以如果我搜索 PNR 部分,它不会停在第一个 [1] 处,而是抓取 PNQ 部分中第一个 [1] 之前的所有内容。
这是我最接近使其工作的方法,但只有当我搜索 PNQ 部分时它才有效:
re.search('SOURCE#.*?\[1\](.*?PNQ.*?.*?HDPGWRF.*?)\*', buf, flags=re.DOTALL).group(1)
这是在梳理了整个 stackoverflow 之后的:(
您可以使用不带
re.DOTALL
标志但带有 re.MULTILINE
标志的模式:
\bSOURCE#.*\s*^\[1](.*\s*^(?!\[\d+]).*\bPN[QR](?:\n(?!\[\d+]).*)*(?:\n\[\d+].*)*)
模式匹配:
\bSOURCE#
从单词边界开始字面匹配.*
匹配该行的其余部分\s*^
匹配可选的空白字符直到行首\[1]
匹配 [1]
(
捕获第 1 组
.*
与该行的其余部分匹配\s*^
匹配可选的空白字符直到行首(?!\[\d+])
负向前瞻,断言各行不以 [digits]
.*\bPN[QR]
匹配行尾的 PNB
或 PNQ
(?:\n(?!\[\d+]).*)*
匹配所有以下不以 [digits]
(?:\n\[\d+].*)*
匹配以下所有以 [digits]
)
关闭第 1 组如果您需要创建编号过滤项的Python对象,您可以尝试:
import re
targets = ["PNR", "PNQ"]
with open("file.txt") as f:
pat = r"\*+\ (SOURCE#\d+) \*+\s+(.+?Remote Host Name : (\w+).+?)(?=\*)"
data = {
m.group(1) : dict(re.findall(r"\[\d+\]\s*(.+?)\s*:\s*(.+)", m.group(2)))
for m in re.finditer(pat, f.read(), flags=re.M|re.S)
if m.group(3) in targets # or ["PNR", "PNQ"]
}
输出:
import json; print(json.dumps(data, indent=4))
{
"SOURCE#24": {
"Source Location [Local/Remote]": "Remote",
"Source directory": "HDPGWRF",
"Directory poll interval": "30",
"File name format": "ACR_FILEFORMAT",
"Delete files from source": "y"
},
"SOURCE#25": {
"Source Location [Local/Remote]": "Remote",
"Source directory": "HDPGWRF",
"Directory poll interval": "30",
"File name format": "ACR_FILEFORMAT",
"Delete files from source": "y"
}
}