在 foreach 中的正则表达式之间使用变量
Using a variable between regexp inside foreach
我需要根据匹配检查点和思科供应商的列表获取所有 mac。我在 Cisco 路由器上执行 "show ip arp",捕获 arp 输出并保存在文件中。现在,我需要逐行检查我有什么mac。
确切地说,我只需要匹配包含 Cisco 和 Checkpoint 供应商的 mac 地址的行。为此,我必须获取 IP 地址、前四位十六进制数字、点和更多的两个十六进制数字来定义 mac 供应商,例如(001c.7f 或 e02f.6d)并将此行打印在文件上.之后,我需要比较 "IP-ARP.txt" 和 "MAC-ADDRESS.txt"(最后一个包含完整的 mac-地址供应商)。如果我的输出匹配,将此行保存到另一个文件中。
这里有一个文件:
IP-ARP.txt
Internet 172.20.14.12 0 001c.7f41.186e ARPA
Internet 172.20.14.13 57 001c.7f41.074e ARPA
Internet 172.20.14.14 0 0200.5ebd.e17d ARPA
Internet 172.20.19.11 - 7081.050f.9402 ARPA
Internet 172.20.19.12 54 7cad.7499.e602 ARPA
Internet 172.20.19.13 7 e02f.6d14.c1bf ARPA
Internet 172.20.19.14 104 e02f.6d15.1d7f ARPA
MAC-ADDRESS.txt
001c.7f
001c.ab
001b.de
001b.ff
001c.cd
001c.de
e02f.6c
e02f.7c
提前致谢!
(由于更改规范再次更新)
我们这里有一个识别字符串列表(OUI MAC 地址部分写成 MAC 地址字符串的片段)和需要检查的数据字符串列表这个列表。
我的解决方案使用 Tcl 库中的 fileutil
包。这不是很有必要,因为您可以使用标准的 Tcl 命令,但它大大简化了脚本。
package require fileutil
定义一些要使用的文件名。
set filename(macaddr) MAC-ADDRESS.txt
set filename(iparp) IP-ARP.txt
set filename(output) output.txt
如果识别字符串列表可能会发生变化,您可能希望每次 运行 您的脚本时都从文件中读取它:
set idlist [::fileutil::cat $filename(macaddr)]
或者如果这些地址很少更改,您可以将其硬编码到脚本中并在必要时进行编辑:
set idlist {001c.7f 001c.ab 001b.de 001b.ff 001c.cd 001c.de e02f.6c e02f.7c}
将输出文件的内容设置为空字符串。
::fileutil::writeFile $filename(output) {}
到 select 你的 IP-ARP.txt
文件中匹配任何这些地址的行,有几种方法可以遍历它。我的建议是使用 fileutil::foreachLine
命令。基本调用是这样的:
::fileutil::foreachLine varName filename script
(第一个参数是一个任意变量名:在每次迭代中当前行将被存储在该变量中。第二个是要遍历的文件的名称,第三个参数是运行 该文件中的每一行一次。)
该脚本使用 string match
命令调用匹配 id 字符串的命令。 regexp
命令可以代替使用,但我认为在这种情况下这是完全没有必要的。 IP-ARP.txt
文件中的每一行要么是空白,要么是一个包含五个元素的正确 Tcl 列表,其中 MAC 地址是第四个。此外,第二个元素是 ip 号,并且只使用以 172 开头的那些。也就是说匹配命令可以这样写:
proc matchid {idlist line} {
set ipAddr [lindex $line 1]
set macAddr [lindex $line 3]
if {[string match 172* $ipAddr]} {
foreach id $idlist {
if {[string match $id* $macAddr]} {
return "$ipAddr $macAddr\n"
}
}
}
}
(以这种方式匹配ip地址只有当地址是点分十进制形式时才有效:如果它可以是任何其他形式,则应该使用Tcllib ip模块来匹配它。)
命令的结果是包含 ip 地址和 MAC 地址的行(如果该行匹配),如果不匹配则为空字符串。
现在让我们遍历 IP-ARP.txt
文件的内容。对于每一行,将内容与 id 列表进行匹配,并获得输出字符串或空字符串。如果字符串不为空,则将其附加到输出文件。
::fileutil::foreachLine line $filename(iparp) {
set res [matchid $idlist $line]
if {$res ne {}} {
::fileutil::appendToFile $filename(output) $res
}
}
就是这样。完整程序:
package require fileutil
set filename(macaddr) MAC-ADDRESS.txt
set filename(iparp) IP-ARP.txt
set filename(output) output.txt
set idlist [::fileutil::cat $filename(macaddr)]
::fileutil::writeFile $filename(output) {}
proc matchid {idlist line} {
set ipAddr [lindex $line 1]
set macAddr [lindex $line 3]
if {[string match 172* $ipAddr]} {
foreach id $idlist {
if {[string match $id* $macAddr]} {
return "$ipAddr $macAddr\n"
}
}
}
}
::fileutil::foreachLine line $filename(iparp) {
set res [matchid $idlist $line]
if {$res ne {}} {
::fileutil::appendToFile $filename(output) $res
}
}
的文档
文档:foreach, if, lindex, package, proc, set, string
(注:评论里的'Hoodiecrow'是我,我之前用的那个nick。)
给定变量 $mac
中的部分 mac 地址(格式为 "xxxx.xx"),以匹配包含以该值开头的 mac 地址的行:
^.*\b$mac[0-9a-f]{2}\.[0-9a-f]{4}\b.*$
如果您的语言匹配 包含 模式的行,您可以省略换行:
\b$mac[0-9a-f]{2}\.[0-9a-f]{4}\b
根据Hoodiecrow的回答,我做到了:
set Ouilist { 0000.0c 0001.42 0001.43 0001.63 0001.64 ... }
set Macs1 [open "IP-ARP.txt" r]
foreach a [split [read -nonewline $Macs1] \n] {
set macAddr [lindex $a 3]
set IP [lindex $a 1]
if { [regexp {(172)\.([0-9]+)\.([0-9]+)\.([0-9]+)} $IP RealIP] } {
regexp {([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])\.([0-9a-f])([0-9a-f])} $macAddr OuiPart
if { $OuiPart in $Ouilist } {
puts "$RealIP $macAddr\r
}
}
这样我就得到了所有以 172 和 mac-address 开头的 ips,它们是 Cisco 和 Checkpoint 供应商。
我需要根据匹配检查点和思科供应商的列表获取所有 mac。我在 Cisco 路由器上执行 "show ip arp",捕获 arp 输出并保存在文件中。现在,我需要逐行检查我有什么mac。
确切地说,我只需要匹配包含 Cisco 和 Checkpoint 供应商的 mac 地址的行。为此,我必须获取 IP 地址、前四位十六进制数字、点和更多的两个十六进制数字来定义 mac 供应商,例如(001c.7f 或 e02f.6d)并将此行打印在文件上.之后,我需要比较 "IP-ARP.txt" 和 "MAC-ADDRESS.txt"(最后一个包含完整的 mac-地址供应商)。如果我的输出匹配,将此行保存到另一个文件中。
这里有一个文件:
IP-ARP.txt
Internet 172.20.14.12 0 001c.7f41.186e ARPA
Internet 172.20.14.13 57 001c.7f41.074e ARPA
Internet 172.20.14.14 0 0200.5ebd.e17d ARPA
Internet 172.20.19.11 - 7081.050f.9402 ARPA
Internet 172.20.19.12 54 7cad.7499.e602 ARPA
Internet 172.20.19.13 7 e02f.6d14.c1bf ARPA
Internet 172.20.19.14 104 e02f.6d15.1d7f ARPA
MAC-ADDRESS.txt
001c.7f
001c.ab
001b.de
001b.ff
001c.cd
001c.de
e02f.6c
e02f.7c
提前致谢!
(由于更改规范再次更新)
我们这里有一个识别字符串列表(OUI MAC 地址部分写成 MAC 地址字符串的片段)和需要检查的数据字符串列表这个列表。
我的解决方案使用 Tcl 库中的 fileutil
包。这不是很有必要,因为您可以使用标准的 Tcl 命令,但它大大简化了脚本。
package require fileutil
定义一些要使用的文件名。
set filename(macaddr) MAC-ADDRESS.txt
set filename(iparp) IP-ARP.txt
set filename(output) output.txt
如果识别字符串列表可能会发生变化,您可能希望每次 运行 您的脚本时都从文件中读取它:
set idlist [::fileutil::cat $filename(macaddr)]
或者如果这些地址很少更改,您可以将其硬编码到脚本中并在必要时进行编辑:
set idlist {001c.7f 001c.ab 001b.de 001b.ff 001c.cd 001c.de e02f.6c e02f.7c}
将输出文件的内容设置为空字符串。
::fileutil::writeFile $filename(output) {}
到 select 你的 IP-ARP.txt
文件中匹配任何这些地址的行,有几种方法可以遍历它。我的建议是使用 fileutil::foreachLine
命令。基本调用是这样的:
::fileutil::foreachLine varName filename script
(第一个参数是一个任意变量名:在每次迭代中当前行将被存储在该变量中。第二个是要遍历的文件的名称,第三个参数是运行 该文件中的每一行一次。)
该脚本使用 string match
命令调用匹配 id 字符串的命令。 regexp
命令可以代替使用,但我认为在这种情况下这是完全没有必要的。 IP-ARP.txt
文件中的每一行要么是空白,要么是一个包含五个元素的正确 Tcl 列表,其中 MAC 地址是第四个。此外,第二个元素是 ip 号,并且只使用以 172 开头的那些。也就是说匹配命令可以这样写:
proc matchid {idlist line} {
set ipAddr [lindex $line 1]
set macAddr [lindex $line 3]
if {[string match 172* $ipAddr]} {
foreach id $idlist {
if {[string match $id* $macAddr]} {
return "$ipAddr $macAddr\n"
}
}
}
}
(以这种方式匹配ip地址只有当地址是点分十进制形式时才有效:如果它可以是任何其他形式,则应该使用Tcllib ip模块来匹配它。)
命令的结果是包含 ip 地址和 MAC 地址的行(如果该行匹配),如果不匹配则为空字符串。
现在让我们遍历 IP-ARP.txt
文件的内容。对于每一行,将内容与 id 列表进行匹配,并获得输出字符串或空字符串。如果字符串不为空,则将其附加到输出文件。
::fileutil::foreachLine line $filename(iparp) {
set res [matchid $idlist $line]
if {$res ne {}} {
::fileutil::appendToFile $filename(output) $res
}
}
就是这样。完整程序:
package require fileutil
set filename(macaddr) MAC-ADDRESS.txt
set filename(iparp) IP-ARP.txt
set filename(output) output.txt
set idlist [::fileutil::cat $filename(macaddr)]
::fileutil::writeFile $filename(output) {}
proc matchid {idlist line} {
set ipAddr [lindex $line 1]
set macAddr [lindex $line 3]
if {[string match 172* $ipAddr]} {
foreach id $idlist {
if {[string match $id* $macAddr]} {
return "$ipAddr $macAddr\n"
}
}
}
}
::fileutil::foreachLine line $filename(iparp) {
set res [matchid $idlist $line]
if {$res ne {}} {
::fileutil::appendToFile $filename(output) $res
}
}
的文档
文档:foreach, if, lindex, package, proc, set, string
(注:评论里的'Hoodiecrow'是我,我之前用的那个nick。)
给定变量 $mac
中的部分 mac 地址(格式为 "xxxx.xx"),以匹配包含以该值开头的 mac 地址的行:
^.*\b$mac[0-9a-f]{2}\.[0-9a-f]{4}\b.*$
如果您的语言匹配 包含 模式的行,您可以省略换行:
\b$mac[0-9a-f]{2}\.[0-9a-f]{4}\b
根据Hoodiecrow的回答,我做到了:
set Ouilist { 0000.0c 0001.42 0001.43 0001.63 0001.64 ... }
set Macs1 [open "IP-ARP.txt" r]
foreach a [split [read -nonewline $Macs1] \n] {
set macAddr [lindex $a 3]
set IP [lindex $a 1]
if { [regexp {(172)\.([0-9]+)\.([0-9]+)\.([0-9]+)} $IP RealIP] } {
regexp {([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])\.([0-9a-f])([0-9a-f])} $macAddr OuiPart
if { $OuiPart in $Ouilist } {
puts "$RealIP $macAddr\r
}
}
这样我就得到了所有以 172 和 mac-address 开头的 ips,它们是 Cisco 和 Checkpoint 供应商。