2015-03-26 1 views
1

J'essaie d'écrire un interligne pour créer un hachage à partir de la sortie de la liste d'interfaces hôte-hôte de VirtualBox. Il ressemble à ceciAccès à la taille du tableau des résultats dans l'appel chaîné

Name:   vboxnet0 
GUID:   77777777-6666-4444-8888-020227202302 
DHCP:   Disabled 
IPAddress:  192.168.42.1 
NetworkMask:  255.255.255.0 
IPV6Address: 
IPV6NetworkMaskPrefixLength: 0 
HardwareAddress: 0a:00:27:00:00:00 
MediumType:  Ethernet 
Status:   Up 
VBoxNetworkName: HostInterfaceNetworking-vboxnet0 

Name:   vboxnet1 
GUID:   77777777-6666-4444-8888-020227202301 
DHCP:   Disabled 
IPAddress:  172.16.0.1 
NetworkMask:  255.255.255.0 
IPV6Address: 
IPV6NetworkMaskPrefixLength: 0 
HardwareAddress: 0a:00:27:00:00:01 
MediumType:  Ethernet 
Status:   Up 
VBoxNetworkName: HostInterfaceNetworking-vboxnet1 

J'ai essayé:

Hash[*`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten(1)] 

Le résultat est:

=> {"Name"=>"vboxnet1", "GUID"=>"786f6276-656e-4174-8000-0a0027000001", "DHCP"=>"Disabled", "IPAddress"=>"172.16.0.1", "NetworkMask"=>"255.255.255.0", "IPV6Address"=>"IPV6NetworkMaskPrefixLength", "0"=> "HardwareAddress", "0a"=>"00", "27"=>"00", "00"=>"01", "MediumType"=>"Ethernet", "Status"=>"Up", "VBoxNetworkName"=>"HostInterfaceNetworking-vboxnet1"} 

À peu près ce que je voulais, mais seulement pour la première interface. Je pensais: "Ok, découpez le tableau en deux et convertissez chaque moitié en hash!".

Mon problème est de savoir comment obtenir la taille du tableau renvoyé par la méthode aplatie et l'utiliser dans le paramètre de la méthode de découpe sans l'affecter à une variable, etc.

je veux dire quelque chose comme:

`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten(1).slice(0..>>>how_to_access_result_object_of_flatten_here<<<.size/2) 

Je ne suis pas connu en Ruby désolé si la question est tout simplement évident, mais j'ai essayé beaucoup de recherche sur Google en vain.

EDIT: L'expression rationnelle pour split dans le champ? Closure/lambda? passé à collect n'est pas correct, car il renvoie une seule chaîne (devrait être deux pour la conversion de hachage au travail) si après le deux-points il n'y a que des espaces qui est le cas pour la ligne commençant par IPV6Address: (non visible dans l'exemple). Je l'ai changé pour split(/:\ /) et maintenant cela fonctionne. L'espace est nécessaire car l'utilisation de deux-points diviserait également l'adresse MAC.

+0

Je ne comprends pas le problème «No tel fichier ou répertoire», je ne peux pas le produire sur ma machine. L'appel à un programme et obtenir sa sortie est exactement ce que je veux. Pour la partie de séparation, voir l'édition de la publication. – frigo

+0

Je ne sais pas pourquoi je pensais que les accolades n'étaient pas prévues - il est clair à la deuxième lecture qu'elles l'étaient. –

Répondre

1

À moins qu'il y ait un Ruby vaudou spécial que je n'ai jamais vu, je suis sûr que la réponse est simple: vous ne pouvez pas.

Cependant, la meilleure approche suivante (au lieu d'attribuer le tableau à une variable) est d'étendre la classe Array et écrire une méthode supplémentaire, comme ceci:

class Array 
    def flatten_and_slice 
    flattened_result = self.flatten(1) 
    self.slice(0..flattened_result.size/2) 
    end 
end 

Ensuite, vous appelez simplement votre nouvelle méthode.

`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten_and_slice 
+0

Ce serait un voodoo très apprécié pour ce problème, je ne sais pas combien de sens cela fait tous ensemble. J'ai trouvé la méthode [tap] (http://ruby-doc.org/core-2.2.1/Object.html#method-i-tap), que je pourrais utiliser pour définir une variable d'environnement, l'utiliser et l'enlever avec un autre robinet, mais on doit savoir quand laisser aller les choses :) et peut-être utiliser votre solution. – frigo

1

Vous pouvez simplement diviser la sortie par ^$ et prendre l'interface que vous voulez:

text = `VBoxManage list hostonlyifs` 
Hash[*text.split(/^$/)[0].split(/\n/).flat_map {|line| line.split(":", 2).map(&:strip) }] 

text.split(/^$/)[0] divise le texte sur des lignes vides et prend la première interface. Ensuite, nous prenons juste ce texte et l'analysons en un hachage en le divisant en lignes individuelles, en le divisant en paires [clé, valeur], et le mappant en un Hash. Cela donne une sortie comme:

{ 
          "Name" => "vboxnet0", 
          "GUID" => "77777777-6666-4444-8888-020227202302", 
          "DHCP" => "Disabled", 
         "IPAddress" => "192.168.42.1", 
        "NetworkMask" => "255.255.255.0", 
        "IPV6Address" => "", 
    "IPV6NetworkMaskPrefixLength" => "0", 
       "HardwareAddress" => "0a:00:27:00:00:00", 
        "MediumType" => "Ethernet", 
         "Status" => "Up", 
       "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet0" 
} 

Si vous voulez générer un tableau de hash, un pour chaque interface, diviser le texte, puis la carte chaque morceau de texte dans un Hash:

text.split(/^$/).map {|chunk| Hash[*chunk.split(/\n/).flat_map {|line| line.split(":", 2).map(&:strip) }] } 

Entraînant :

[ 
    [0] { 
           "Name" => "vboxnet0", 
           "GUID" => "77777777-6666-4444-8888-020227202302", 
           "DHCP" => "Disabled", 
          "IPAddress" => "192.168.42.1", 
         "NetworkMask" => "255.255.255.0", 
         "IPV6Address" => "", 
     "IPV6NetworkMaskPrefixLength" => "0", 
        "HardwareAddress" => "0a:00:27:00:00:00", 
         "MediumType" => "Ethernet", 
          "Status" => "Up", 
        "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet0" 
    }, 
    [1] { 
           "Name" => "vboxnet1", 
           "GUID" => "77777777-6666-4444-8888-020227202301", 
           "DHCP" => "Disabled", 
          "IPAddress" => "172.16.0.1", 
         "NetworkMask" => "255.255.255.0", 
         "IPV6Address" => "", 
     "IPV6NetworkMaskPrefixLength" => "0", 
        "HardwareAddress" => "0a:00:27:00:00:01", 
         "MediumType" => "Ethernet", 
          "Status" => "Up", 
        "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet1" 
    } 
]