我正在编写一个脚本,从配置数据分布在多行中的文件中解析出某些值,并且在Ruby中遇到了很多麻烦。数据如下所示。将数据联系在一起的部分是单元号。我需要做的是从这个数据中抓取Unit, adminpaddress, InterfaceDisplayString和Name值,并以这样一种有意义的方式保存它。对我来说,多维Perl散列是完美的,但是语法超出了我对Ruby语言的理解。
如果你能提供任何帮助,我将不胜感激。我希望数据是像下面这样的散列:
{Unit0} => {IPAddress => 10.5.52.60, Name => 440_6PT_6AS_inf4, Port = 10_10},
{Unit1} => ...
我已经能够通过以下操作创建所有重要行的数组:
if (line =~ /WaTestProfile,Unit[d+]/)
# Manipulate the data first to remove pesky special characters
result = line.gsub(/[^0-9A-Za-z,.,{}_ ]/, '')
if result !~ /DDOS|PhysIf/
temp_line += [ "#{result}" ]
end
end
然后我可以使用一些正则表达式拉出特定的字段:
unit_array.sort.each_with_index do |line, idx|
if result = line.match(/W[a|r]TestProfile,Unit(?:d+),AdminIPAddresss+{(.*)}/)
temp = result.captures
ip_array += [ temp ]
printf "I captured #{temp}n"
end
if result = line.match(/W[a|r]TestProfile,Unit(?:d+),Interface,0,InterfaceDisplayStrings+{(.*)}/)
temp = result.captures
port_array += [ temp]
printf "I have captured #{temp}n"
end
if result = line.match(/W[a|r]TestProfile,Unit(?:d+),Interface,0,Names+{(.*)}/)
temp = result.captures
name_array += [ temp ]
printf "Finally, I captured #{temp}n"
end
end
这将所有内容放入三个单独的数组中:从Unit 0到5自上而下,但我不能将其带入下一步并将其粘贴到多维数组中,我认为上面的代码也可以改进。
WaTestProfile,Unit0,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit0,Interface,0,DDOSAttacks {}
WaTestProfile,Unit0,Interface,0,DDOSConfig {}
WaTestProfile,Unit0,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit0,Interface,0,InterfaceDisplayString {10_10}
WaTestProfile,Unit0,Interface,0,Name {440_6PT_6AS_inf5}
WaTestProfile,Unit0,Interface,0,PhysIf {10}
WaTestProfile,Unit1,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit1,Interface,0,DDOSAttacks {}
WaTestProfile,Unit1,Interface,0,DDOSConfig {}
WaTestProfile,Unit1,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit1,Interface,0,InterfaceDisplayString {8_8}
WaTestProfile,Unit1,Interface,0,Name {440_6PT_6AS_inf4}
WaTestProfile,Unit1,Interface,0,PhysIf {8}
WaTestProfile,Unit2,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit2,Interface,0,DDOSAttacks {}
WaTestProfile,Unit2,Interface,0,DDOSConfig {}
WaTestProfile,Unit2,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit2,Interface,0,InterfaceDisplayString {2_2}
WaTestProfile,Unit2,Interface,0,Name {440_6PT_6AS_inf1}
WaTestProfile,Unit2,Interface,0,PhysIf {2}
WaTestProfile,Unit3,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit3,Interface,0,DDOSAttacks {}
WaTestProfile,Unit3,Interface,0,DDOSConfig {}
WaTestProfile,Unit3,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit3,Interface,0,InterfaceDisplayString {4_4}
WaTestProfile,Unit3,Interface,0,Name {440_6PT_6AS_inf2}
WaTestProfile,Unit3,Interface,0,PhysIf {4}
WaTestProfile,Unit4,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit4,Interface,0,DDOSAttacks {}
WaTestProfile,Unit4,Interface,0,DDOSConfig {}
WaTestProfile,Unit4,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit4,Interface,0,InterfaceDisplayString {6_6}
WaTestProfile,Unit4,Interface,0,Name {440_6PT_6AS_inf3}
WaTestProfile,Unit4,Interface,0,PhysIf {6}
WaTestProfile,Unit5,AdminIPAddress {10.5.52.60}
WaTestProfile,Unit5,Interface,0,DDOSAttacks {}
WaTestProfile,Unit5,Interface,0,DDOSConfig {}
WaTestProfile,Unit5,Interface,0,DDOSEnabled {off}
WaTestProfile,Unit5,Interface,0,InterfaceDisplayString {0_0}
WaTestProfile,Unit5,Interface,0,Name {440_6PT_6AS_inf0}
WaTestProfile,Unit5,Interface,0,PhysIf {0}
所以我认为这可能是你正在寻找的,虽然它是有点难以理解的问题。这是我的解决方案,我会把每一部分都过一遍。
hsh = Hash.new()
File.open('config.txt', 'r').each_line do |line|
match =
/WaTestProfile,
(?<unit>Unitd+) # match the unit and unit number
,.* # match the comma and all the way up to the property
(?<property>AdminIPAddress|InterfaceDisplayString|Name) # match the property
s+ # match all spaces up to the property value
{(?<property_value>.*)} # match the property value
/x =~ line
if match
hsh[unit.to_sym] ||= {}
hsh[unit.to_sym][property.to_sym] = property_value
end
end
hsh.each do |key, value|
puts key.to_s + value.to_s
end
这只是创建一个哈希,我们也可以做hsh = {}
hsh = Hash.new()
然后打开文件进行读取,并读取每一行。我们尝试在每一行中找到匹配项。这里我使用了一种更高级的regex形式,使用命名捕获并忽略空白,因为它有点复杂,因此更容易阅读
match =
/WaTestProfile,
(?<unit>Unitd+) # match the unit and unit number
,.* # match the comma and all the way up to the property
(?<property>AdminIPAddress|InterfaceDisplayString|Name|PhysIf) # match the property
s+ # match all spaces up to the property value
{(?<property_value>.*)} # match the property value
/x =~ line
现在我可以引用变量unit
并获得整个单元和单元号。
我们还在开始时使用match =
,以便我们可以从等式中删除DDOS行。
最后我们检查是否有匹配。如果有的话,我们要么创建一个新键对应于顶层哈希中的一个哈希,要么获取一个现有的哈希。然后我们将属性设置为正确的属性值。我想既然你没有在键周围加上引号,你希望它们是符号,这可能是一个更好的主意。
if match
hsh[unit.to_sym] ||= {}
hsh[unit.to_sym][property.to_sym] = property_value
end
最终输出如下所示:
Unit0{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"10_10", :Name=>"440_6PT_6AS_inf5"}
Unit1{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"8_8", :Name=>"440_6PT_6AS_inf4"}
Unit2{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"2_2", :Name=>"440_6PT_6AS_inf1"}
Unit3{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"4_4", :Name=>"440_6PT_6AS_inf2"}
Unit4{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"6_6", :Name=>"440_6PT_6AS_inf3"}
Unit5{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"0_0", :Name=>"440_6PT_6AS_inf0"}
所有包含在散列hsh
嘘:
如果你想要一个更短的版本,在这里:
hsh = {}
File.open('config.txt', 'r').each_line do |line|
if /WaTestProfile,(?<unit>Unitd+),.*(?<property>AdminIPAddress|InterfaceDisplayString|Name)s+{(?<property_value>.*)}/x =~ line
hsh[unit.to_sym] ||= {}
hsh[unit.to_sym][property.to_sym] = property_value
end
end
p hsh
输出:{:Unit0=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"10_10", :Name=>"440_6PT_6AS_inf5"}, :Unit1=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"8_8", :Name=>"440_6PT_6AS_inf4"}, :Unit2=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"2_2", :Name=>"440_6PT_6AS_inf1"}, :Unit3=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"4_4", :Name=>"440_6PT_6AS_inf2"}, :Unit4=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"6_6", :Name=>"440_6PT_6AS_inf3"}, :Unit5=>{:AdminIPAddress=>"10.5.52.60", :InterfaceDisplayString=>"0_0", :Name=>"440_6PT_6AS_inf0"}}