gpt4 book ai didi

python - 从 DNS 区域文件中提取源域的脚本不会跳过带有前导空格的行

转载 作者:行者123 更新时间:2023-12-01 01:02:10 25 4
gpt4 key购买 nike

我正在清理我们的 DNS 区域文件,以便提取仅包含 CNAMEA 记录的源域并消除所有注释,TXTMXSRV 记录。最重要的是,我想自动化这个过程。

我成功创建了一个正则表达式,可用于在 Sublime Text 中执行查找和替换,并需要进行几次迭代才能达到所需的结果。

让我们以以下示例 DNS 区域文件为例:

$ORIGIN example.com.
@ 3600 SOA ns1.p30.dynect.net. (
zone-admin.dyndns.com. ; address of responsible party
2016072701 ; serial number
86400 IN NS ns1.p30.dynect.net.
3600 IN MX 10 mail.example.com.
60 IN A 204.13.248.106
abc TXT "v=spf1 includespf.dynect.net ~all"
mail IN A 204.13.248.106
vpn IN TXT v=spf1 includespf.dynect.net ~all"
vpn2 IN MX v=spf1 includespf.dynect.net ~all"
webapp IN A 216.146.46.10
#webapp1 IN A 216.146.46.10
xyz IN CNAME example.com.
webapp IN SRV 216.146.46.11
;webapp2 IN A 216.146.46.11

第 1 步

使用它来“查找”

(^;.*)|(^#.*)|(^\$.*)|(^@.*)|(.*IN\h+MX.*)|(.*IN\h+TXT.*)|(.*IN\h+SRV.*)|(.*IN\h+NS.*)|(.*\h+TXT.*)|(\h.+)|(^[\n\r\h]+)

然后什么都不替换。

这将清理区域文件并仅显示指向 CNAMEA 记录的源域。

步骤 2

使用以下内容进行“查找”

(.+$)

并将其替换为

\1.example.com

结果是附加了原始域的源域列表:

mail.example.com
webapp.example.com
xyz.example.com


我现在正在尝试编写一个 Python 脚本,为给定的区域文件执行上述操作并将其输出到 .txt 文件。

Wiktor Stribiżew Stack Overflow 上的 RegEx 和 Python 大神帮我写了以下内容:

import re

regex = re.compile(r'^(?:\s+|[;#$@].*)|.*IN\s+(?:MX|TXT|SRV|NS).*|.*\s+TXT.*|\s.+')
with open('1.txt', 'r',encoding='UTF8') as dns:
with open('2.txt', 'w',encoding='UTF8') as output:
for line in dns:
if line.strip():
line = regex.sub('', line.strip())
if line:
output.write("{}.example.com\n".format(line))

不幸的是,脚本的输出是这样的:

zone-admin.dyndns.com..example.com
2016072701.example.com
60.example.com
mail.example.com
webapp.example.com
xyz.example.com

脚本不会省略以空格开头的行。我做错了什么?

最佳答案

看起来您有两个错误,每个错误都会导致错误使用以空格开头的行。


第一个错误出现在语句中

line = regex.sub('', line.strip())

在将行传递给 sub() 方法之前,会去除所有前导空格。因此,正则表达式永远不会看到任何以空格开头的行。

要解决此问题,需要在调用 sub() 方法之后调用 strip() 方法:

line = regex.sub('', line).strip()

请注意,strip() 的全部原因是删除尾随换行符,将 line 设置为要忽略的行的空字符串。可以使用一个简单的测试来检查这一点,因为空字符串是假的。

作为替代方案,可以省略此调用,而是可以修改正则表达式以删除换行符。 (这可以通过将所有“尾随”.* 替换为 [\s\S]* 来完成。)


第二个错误出现在正则表达式中,它只匹配该行的前导空白部分,而不是整个行。这会导致 sub() 方法本质上去除前导空格!
Demo 1 🔗 1

regex = re.compile(r'^(?:\s+|[;#$@].*)|.*IN\s+(?:MX|TXT|SRV|NS).*|.*\s+TXT.*|\s.+')
↑_↑
|
only matches the leading white-space part, not the whole line


快速解决方法是将非捕获组的右括号向前移动:
Demo 2 🔗 1

regex = re.compile(r'^(?:\s+|[;#$@]).*|.*IN\s+(?:MX|TXT|SRV|NS).*|.*\s+TXT.*|\s.+')
↑ ↓


请注意,可以通过实现空白元字符 \s 可以在字符类中移动来创建更简单的正则表达式,并且我们只需要检查该行的第一个字符:< br/> Demo 3 🔗 1

regex = re.compile(r'^[\s;#$@].*|.*IN\s+(?:MX|TXT|SRV|NS).*|.*\s+TXT.*|\s.+')


最后,可以通过使用否定前瞻(而不是显式地、详尽地)匹配每个指向 CNAME 或 A 记录的非注释、非前导空白行来实现进一步的简化。指向非 CNAME/非 A 记录的匹配行:
Demo 4 🔗 1

regex = re.compile(r'^(?:[\s;#$@]|(?!.*IN\s+[AC])).*|\s.+')

或者,如果您更喜欢更少的嵌套(加上它短一个字符;-)):
Demo 5 🔗 1

regex = re.compile(r'^[\s;#$@].*|^(?!.*IN\s+[AC]).*|\s.+')


这是使用上面最后一个正则表达式的代码的完整工作版本:

import re

regex = re.compile(r'^[\s;#$@].*|^(?!.*IN\s+[AC]).*|\s.+')
with open('1.txt', 'r',encoding='UTF8') as dns:
with open('2.txt', 'w',encoding='UTF8') as output:
for line in dns:
if line.strip():
line = regex.sub('', line).strip()
if line:
output.write("{}.example.com\n".format(line))
<小时/>

1 所有演示正则表达式都已调整(最后一个空白元字符 \s 已替换为空格)以允许多个行标志用于显示完成替换后的所有结果行(在“替换”框中)。这不会影响正则表达式的功能,因为测试字符串仅包含空格和换行符,没有其他空格。

关于python - 从 DNS 区域文件中提取源域的脚本不会跳过带有前导空格的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55697261/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com