Ruby - 解析文件,同时跟踪多条线路上的连接数据

时间:2014-05-02 16:24:39

标签: ruby file hash multidimensional-array

我正在编写一个脚本来解析文件中的某些值,其中配置数据分布在多行中,并且在Ruby中执行它时遇到了很多麻烦。数据如下所示。将数据绑定在一起的部分是单元号。我需要做的是从这些数据中获取Unit,AdminIPAddress,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+),AdminIPAddress\s+\{(.*)\}/)
    temp = result.captures
    ip_array += [ temp ]
    printf "I captured #{temp}\n"
  end
  if result = line.match(/W[a|r]TestProfile,Unit(?:\d+),Interface,0,InterfaceDisplayString\s+\{(.*)\}/)
    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,Name\s+\{(.*)\}/)
    temp = result.captures
    name_array += [ temp ]
    printf "Finally, I captured #{temp}\n"
  end
end

这将所有内容分成三个独立的数组:从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}\

1 个答案:

答案 0 :(得分:0)

所以我认为这可能是你正在寻找的东西,尽管很难理解这个问题。这是我的解决方案,我将逐一介绍。

hsh = Hash.new()

File.open('config.txt', 'r').each_line do |line|
  match =
  /WaTestProfile,
    (?<unit>Unit\d+)  # 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()

然后我们打开文件进行阅读并读取每一行。在每一行我们都试图找到匹配。我在这里使用了更高级的正则表达式,使用了命名捕获并忽略了空格,因为它更复杂,所以它更容易阅读

  match =
  /WaTestProfile,
    (?<unit>Unit\d+)  # 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>Unit\d+),.*(?<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"}}