IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

[perl 5.26][Array/Hash/Map] Script pour éditer /etc/hosts


Sujet :

Langage Perl

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut [perl 5.26][Array/Hash/Map] Script pour éditer /etc/hosts
    Bonjour,

    Je suis en train de tenter quelque chose avec mes élèves.
    Nous sommes dans une classe où règne Microsoft et donc où nous ne savons pas travailler.
    Impossible d'éditer /etc/hosts (Windows\system32\drivers\etc) par manque de droits suffisants, et pour l'apprentissage du Web dynamique on est un peu mal.
    Et pour la liste DNS pour chaque poste c'est pareil on ne peut pas la modifier.

    J'ai donc mon portable avec Apache, bind9/named, etc... permettant d'heberger les sites de mes élèves.
    J'ai créé un script bash qui permet (un peu comme Wamp) en une ligne de commande de créer autant d'hôtes virtuels avec les dossiers "squelettes" pour les sites en modifiant le contenu des fichiers "vhost.template".

    Maintenant, dans un premier temps, j'aimerais créer un script perl, il me semble que c'est le meilleur langage pour ce genre de traitement de données qui me permettrait de "mettre de l'ordre" dans le fichier /ec/hosts.
    Vu que la liste DNS n'est pas encore modifiée au niveau de la classe, l'administrateur ne m'a pas encore répondu à ce sujet, je dois passer par le /etc/hosts de mon système pour "résoudre les noms de domaines".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    use strict;
    use warnings;
     
    use experimental 'smartmatch';
     
    my @ipaddresses = ('');
     
    my $targetfile="/etc/hosts";
     
    my $ipentry="";
    my @domains = ('');
     
    open(my $descripteur,'<:encoding(UTF-8)', $targetfile) or die "$targetfile not found :{";
     
    while(my $ligne = <$descripteur>)  # tant que nous ne sommes pas arrivés à la fin du fichier
    {
    	chomp $ligne;				# on enlève le caractère '\n' de fin de ligne
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne); # on "splitte" à un ou plusieurs espaces ou à une tabulation
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			print "IP trouvée --> $ipentry \n";
     
    			push(@ipaddresses,$ipentry);
    		}
    	}
    }
    J'aimerais créer un "hash" ou "map" avec une clef (adresse IP) et un ou plusieurs domaines.
    Est-ce possible en perl ou dois-je passer par MySQL ?

    Instinctivement je ferais ceci mais je n'arrive pas à parcourir le tableau de domaines par la suite...

    A la lecture du fichier j'obtients le tableau @domains via le split.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    my %hashEntries=('');
     
    if(!$ipentry ~~ $hashEntries{$ipentry}) $hashEntries{$ipentry}=[ @domains ]; # si je mets @domains sans les crochets j'ai le nombre d'éléments au lieu de la référence du tableau HASH[...].
    else
    {
     # c'est ici que je n'arrive pas à "pusher" les domaines à ceux qui existent déjà
     my @existingDomains=$hashEntries{$ipentry};
     
    }
    Pourriez-vous m'éclairer sur ce sujet ?
    [EDIT]
    Oui, le fichier /etc/hosts à la lecture de ses lignes, risque de contenir plusieurs fois une certaine adresse IP, par exemple 127.0.0.6 pourrait apparaître trois ou quatre fois avec des domaines différents (en nombre aussi)...
    127.0.0.6 www.test1.ecole.be
    ...
    ...
    ...
    127.0.0.6 www.test2.ecole.be test3 test4
    ...
    ...
    127.0.0.6 www.test5.ecole.be
    Le but du jeu serait de "refondre" un /etc/hosts avec une seule ligne pour 127.0.0.6 avec tous les domaines trouvés à la lecture de celui-ci.

    1. je parcoure /etc/hosts
    2. je lis chaque ligne et détecte si il s'agit d'une IPv4
    3. je lie une adresse IP avec une liste de domaines (au lieu de map dans le titre j'aurais dû mettre lists)
    4. si je retrouve la même ip j'ajoute les domaines à ceux de la liste correspondant à la clef représentée par l'adresse IP
    5. je renomme le fichier /etc/hosts
    6. je relis le fichier renommé et dès que je trouve une ipv4 je ne recopie pas la ligne dans /etc/hosts
    7. une fois la fin du fichier renommé atteinte j'écris les lignes contenant l'adresse IP et les domaines liés dans /etc/hosts

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    En relisant et en essayant de comprendre le post Merci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    use strict;
    use warnings;
     
    use experimental 'smartmatch';
    use Data::Dump 'dump';
     
    my @ipaddresses = ('');
     
    my $targetfile="/etc/hosts";
     
    my $ipentry="";
    my @domains = ('');
     
    my %hashEntries=('');
     
     
    open(my $descripteur,'<:encoding(UTF-8)', $targetfile) or die "$targetfile not found :{";
     
    while(my $ligne = <$descripteur>) 			# tant que nous ne sommes pas arrivés à la fin du fichier
    {
    	chomp $ligne;													# on enlève le caractère '\n' de fin de ligne
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne);									# on "splitte" à un ou plusieurs espaces ou à une tabulation
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			print "IP trouvée --> $ipentry \n";
    			$hashEntries{$ipentry} = [ "@domains" ];
     
    		}
    	}
    }
     
    print dump(%hashEntries)."\n";
     
    #my @domainnames = (@ipaddresses);
    #print "Elements dans \@domainnames: ".(@domainnames-1)."\n";
     
    close($descripteur);
    J'obtiens au moins les valeurs dumpées je vais voir quand je fais un simple print ce que cela donne... mais je pense avoir saisi le principe...

  3. #3
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà où je coince...

    sirius:/utilitaires/perl/2023/apachehelper # ./apachehelper.pl
    IP trouvée --> 127.0.0.1
    IP trouvée --> 127.0.0.2
    IP trouvée --> 127.0.0.5
    IP trouvée --> 127.0.0.3
    IP trouvée --> 127.0.0.4
    IP trouvée --> 127.0.0.6
    IP trouvée --> 127.0.0.254
    [Add] Nombre d'éléments: ARRAY(0x555a66a4e7e8)
    [Add] Nombre d'éléments: ARRAY(0x555a66a4e7e8) test.com test2.com test3.com
    (
    "127.0.0.3",
    ["server.mysql.dezordi.world"],
    "127.0.0.1",
    ["localhost"],
    "127.0.0.5",
    ["www.server.dezordi.world"],
    "127.0.0.4",
    ["www.memory.dezordi.world"],
    "127.0.0.2",
    ["www.secureserver.dezordi.world"],
    "127.0.0.6",
    ["www.examendecembre.uaa12.test"],
    "127.0.0.254",
    ["www.exercicePHP3.test"],
    )
    [After no dump] Test -> ARRAY(0x555a66a4e7e8)
    Je pense que si je ne sais pas faire de print (je maîtrise pas trop le dump) je ne saurais pas écrire dans un fichier donné... et puis le dump formatte les données bizaremment et ne convient pas pour /etc/hosts.
    Ici j'ai du mal à ajouter des éléments à une liste déjà existante...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    use strict;
    use warnings;
     
    use experimental 'smartmatch';
    use Data::Dump 'dump';
     
    my @ipaddresses = ('');
     
    my $targetfile="/etc/hosts";
     
    my $ipentry="";
    my @domains = ('');
     
    my %hashEntries;
     
     
    open(my $descripteur,'<:encoding(UTF-8)', $targetfile) or die "$targetfile not found :{";
     
    while(my $ligne = <$descripteur>) 			# tant que nous ne sommes pas arrivés à la fin du fichier
    {
    	chomp $ligne;													# on enlève le caractère '\n' de fin de ligne
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne);									# on "splitte" à un ou plusieurs espaces ou à une tabulation
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			print "IP trouvée --> $ipentry \n";
    			$hashEntries{$ipentry} = [ "@domains" ];
    			push(@ipaddresses,$ipentry);
    		}
    		else
    		{
    			my @temp=$hashEntries{$ipentry};
    			print "[Add] Nombre d'éléments: @temp\n";
    			push(@temp,@domains);
    			print "[Add] Nombre d'éléments: @temp\n";
     
    		}
    	}
    }
     
    print dump(%hashEntries)."\n";
    print "[After no dump] Test -> ".$hashEntries{'127.0.0.6'}."\n";
     
    close($descripteur);

  4. #4
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà au moins quelque chose maintenant je ne sais pas comment accéder au contenu du hash...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    while(my $ligne = <$descripteur>) 			
    {
    	chomp $ligne;													
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne);									
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			print "IP trouvée --> $ipentry \n";
    			$hashEntries{$ipentry} = [ "@domains" ];
    			push(@ipaddresses,$ipentry);
    		}
    		else
    		{
    			my @temp=$hashEntries{$ipentry};
    			print "[Add] Nombre d'éléments: @temp\n";
    			push(@temp,[@domains]);
     
    			$hashEntries{$ipentry} = [@temp];
    			print "[Add] Nombre d'éléments: @temp\n";
     
    		}
    	}
    }
    Output qui me paraît intéressant:

    sirius:/utilitaires/perl/2023/apachehelper # ./apachehelper.pl
    IP trouvée --> 127.0.0.1
    IP trouvée --> 127.0.0.2
    IP trouvée --> 127.0.0.5
    IP trouvée --> 127.0.0.3
    IP trouvée --> 127.0.0.4
    IP trouvée --> 127.0.0.6
    IP trouvée --> 127.0.0.254
    [Add] Nombre d'éléments: ARRAY(0x555f403217e8)
    [Add] Nombre d'éléments: ARRAY(0x555f403217e8) ARRAY(0x555f403220a0)
    (
    "127.0.0.6",
    [
    ["www.examendecembre.uaa12.test"],
    ["test.com", "test2.com", "test3.com"],
    ],
    "127.0.0.2",
    ["www.secureserver.dezordi.world"],
    "127.0.0.3",
    ["server.mysql.dezordi.world"],
    "127.0.0.254",
    ["www.exercicePHP3.test"],
    "127.0.0.1",
    ["localhost"],
    "127.0.0.4",
    ["www.memory.dezordi.world"],
    "127.0.0.5",
    ["www.server.dezordi.world"],
    )
    [After no dump] Test -> ARRAY(0x555f403411f8)
    J'aimerais pouvoir parcourir le hash et constituer quelque chose comme


  5. #5
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foreach my $key (keys %hashEntries)
    {
    	my @temp=$hashEntries{$key};
    	print "[After no dump] Test 2 $key -> @temp\n";
    }
    J'arrive pas à faire comprendre à Perl que @temp n'est pas l'adresse du tableau mais les éléments à afficher lol ^^

  6. #6
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Avec ceci j'y suis presque...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    foreach my $key (keys %hashEntries)
    {
    	my @temp=$hashEntries{$key};
     
    	#print "Elements: ".@temp."\t";
     
    	print "[After no dump] Test 2 $key ->\t";
    	foreach my $element (@temp)
    	{	
    		if($element ~~ /ARRAY/)
    		{
    			print "Array détecté...\t";
    			foreach my $autreelement (@$element)
    			{
    					print "[@$autreelement]\n";
    			}
    		}
    		print "[@$element]\n";
    	}
    }
    Mais encore une fois il m'est impossible avec mes connaissances actuelles de Perl de "détecter qu'il s'agit d'une liste/array" et du coup je suis obligé de faire des "workarounds" bancaux ^^
    sirius:/utilitaires/perl/2023/apachehelper # ./apachehelper.pl
    IP trouvée --> 127.0.0.1
    IP trouvée --> 127.0.0.2
    IP trouvée --> 127.0.0.5
    IP trouvée --> 127.0.0.3
    IP trouvée --> 127.0.0.4
    IP trouvée --> 127.0.0.6
    IP trouvée --> 127.0.0.254
    [Add] Nombre d'éléments: ARRAY(0x5598af4ebef0)
    [Add] Nombre d'éléments: ARRAY(0x5598af4ebef0) ARRAY(0x5598af50f928)
    (
    "127.0.0.254",
    ["www.exercicePHP3.test"],
    "127.0.0.6",
    [
    ["www.examendecembre.uaa12.test"],
    ["test.com", "test2.com", "test3.com"],
    ],
    "127.0.0.5",
    ["www.server.dezordi.world"],
    "127.0.0.2",
    ["www.secureserver.dezordi.world"],
    "127.0.0.1",
    ["localhost"],
    "127.0.0.4",
    ["www.memory.dezordi.world"],
    "127.0.0.3",
    ["server.mysql.dezordi.world"],
    )
    [After no dump] Test 2 127.0.0.254 -> [www.exercicePHP3.test]
    [After no dump] Test 2 127.0.0.6 -> Array détecté... [www.examendecembre.uaa12.test]
    [test.com test2.com test3.com]
    [ARRAY(0x5598af4ebef0) ARRAY(0x5598af50f928)] /!\ AU SECOURS /!\ COMMENT CA APPARAIT DANS LA LISTE ?????
    [After no dump] Test 2 127.0.0.5 -> [www.server.dezordi.world]
    [After no dump] Test 2 127.0.0.2 -> [www.secureserver.dezordi.world]
    [After no dump] Test 2 127.0.0.1 -> [localhost]
    [After no dump] Test 2 127.0.0.4 -> [www.memory.dezordi.world]
    [After no dump] Test 2 127.0.0.3 -> [server.mysql.dezordi.world]

  7. #7
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    use strict;
    use warnings;
    use experimental 'smartmatch';
     
    use File::Copy;
    #use Data::Dump 'dump';
     
    my @ipaddresses = ('');
     
    my $targetfile="/etc/hosts";
     
    my $ipentry="";
     
    my @domains;
    my $lesdomaines;
    my %hashEntries;
     
    my $doyourjob=0;
     
     
    open(my $descripteur,'<:encoding(UTF-8)', $targetfile) or die "$targetfile not found :{";
     
    while(my $ligne = <$descripteur>) 			# tant que nous ne sommes pas arrivés à la fin du fichier
    {
    	chomp $ligne;													# on enlève le caractère '\n' de fin de ligne
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne);									# on "splitte" à un ou plusieurs espaces ou à une tabulation
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			#print "IP trouvée --> $ipentry \n";
    			$hashEntries{$ipentry} = [ "@domains" ];											# contre intuitif... un "add" ou "+=" ou quelque chose qui pourrait noter qu'on ajoute à ce qui existe déjà...
    			push(@ipaddresses,$ipentry);
    		}
    		else
    		{
    			my @temp=$hashEntries{$ipentry};
    			push(@temp,[@domains]);
    			$hashEntries{$ipentry} = [@temp];															# contre intuitif... un "add" ou "+=" ou quelque chose qui pourrait noter qu'on ajoute à ce qui existe déjà...
    			$doyourjob=1;
    		}
    	}
    }
     
    #print dump(%hashEntries)."\n";
    close($descripteur);
     
    # ne faire ceci que si nous avons trouvé deux entrées IPv4 distinctes...
     
    if($doyourjob)
    {
    	#renommer le fichier /etc/hosts en /etc/hosts.apachehelper
    	copy $targetfile, "/etc/hosts.apachehelper" or die "$targetfile can not be copied ($!) :{";
    	unlink $targetfile;
    	open(my $descWRITE,'>:encoding(UTF-8)',$targetfile); 
     
    	#ouvrir le fichier renommé en lecture et /etc/hosts en écriture
     
    	open(my $descREAD,'<:encoding(UTF-8)', "/etc/hosts.apachehelper") or die "file not found :{";
     
    	# lire chaque ligne du fichier /etc/hosts.apachehelper
     
    	while(my $ligne = <$descREAD>)
    	{
    		# ne recopier que les lignes ne CONTENANT PAS d'adresse IPv4
    		if(!($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/))
    		{
    			chomp $ligne;
    			#print $ligne."\t\t\t--> recopiée \n";
    			print $descWRITE $ligne."\n";
    		}
    	}
     
    	close($descREAD);
     
    	foreach my $key (keys %hashEntries)
    	{
    		my @temp=$hashEntries{$key};
     
    		foreach my $element (@temp)
    		{	
    			if($element ~~ /ARRAY/)
    			{
    				foreach my $autreelement (@$element)
    				{
    						$lesdomaines.="@$autreelement";
    						$lesdomaines.="\t";
    				}
    			}
    			else
    			{
    				$lesdomaines.="@$element";
    				$lesdomaines.="\t";
    			}
    		}
    		print $key."\t".$lesdomaines."\n";
    		$ipentry=$key."\t".$lesdomaines."\n";
     
    		print $descWRITE $ipentry;
     
    		$lesdomaines="";
    	}
     
    	close($descWRITE);
    }
    else
    {
    	print "Nothing to do... /etc/hosts is not messed ^^\n";
    }
    Voilà ça marche !!

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Quelle aventure!

    Tu peux aussi te simplifier la vie en utilisant un hash à 2 dimensions (pour éviter les noms de domaine en double sans avoir à vérifier quoi que ce soit). Pour ma part je me passerais de vérifier que le fichier a besoin d'être traité et je le ferais systématiquement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    use strict;
    use warnings;
     
    use File::Copy qw(move);
     
    open(my $fhi, '<', 'osts') or die "osts not found\n";
    open(my $fho, '>', 'newosts') or die "can't create newosts\n";
     
    my %IPs;
     
    while(<$fhi>) {
        if (/^ ( \d{1,3} (?: \. \d{1,3} ){3} ) \s+ (.*) /x) {
            $IPs{$1}{$_} = 1 for split(' ', $2);
        } else {
            print $fho $_;
        }
    }
     
    close $fhi;
     
    for(keys %IPs) {
        print $fho "$_\t", join("\t", keys %{$IPs{$_}}), "\n";
    }
     
    close $fho;
     
    move('osts', 'osts.old') or die "error on renaming osts\n";
    move('newosts', 'osts') or die "error on renaming newosts\n";
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  9. #9
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui merci CosmoKnacki ^^

    Ca fait un bail que j'ai plus fait de Perl, et j'ai fait du gros n'importe quoi.
    Je me suis attelé à refaire des tests avec les tableaux et les hashes, et j'ai ceci qui me semble mieux, mais j'ai toujours du mal avec les "références" qui ne sont pas les mêmes qu'en langage C... mais je suis en train de rebouquiner
    le Perl et ses bases donc, je reviendrais si j'ai compris quelque chose lol.

    Le Perl est passionnant je l'ai découvert en 1999... et je m'en sers pour le cgi-bin web, les petits outils d'admin pour mon système à la maison ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    while(my $ligne = <$descripteur>) 			# tant que nous ne sommes pas arrivés à la fin du fichier
    {
    	chomp $ligne;													# on enlève le caractère '\n' de fin de ligne
     
    	if($ligne =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/)
    	{
    		($ipentry,@domains)=split('\s{1,}|\t',$ligne);									# on "splitte" à un ou plusieurs espaces ou à une tabulation
     
    		if(!($ipentry ~~ @ipaddresses))
    		{
    			# si adresse IP pas trouvée 
    			$hashIPv4Hosts{$ipentry} = [ @domains ];											# on associe @domains avec l'adresse IP 
    			push(@ipaddresses,$ipentry);																	# on ajoute l'adresse IP dans le tableau ipaddresses
    		}
    		else
    		{
    			my $recupHosts=$hashIPv4Hosts{$ipentry};
    			push( @$recupHosts,"@domains");
    			$hashIPv4Hosts{$ipentry}=~[ @domains ];												# on remplace les hosts liés à l'adresse IP
    			$doyourjob=1;
    		}
    	}
    }
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    foreach my $ipaddress (@ipaddresses)
    {
      my $hoststowrite=$hashIPv4Hosts{$ipaddress};
      my $lineToWrite=$ipaddress."\t"."@$hoststowrite"."\n";
      print $lineToWrite;
      print $descWRITE $lineToWrite;
    }
    ...

    Je me suis pris la tête avec la pseudo-détection des éléments ARRAY alors qu'en se posant et réfléchissant il y avait moyen de faire cela plus "clairement", même si au vu de ta soluce il y encore moyen en Perl
    de faire avec moins de lignes de code lol ^^

  10. #10
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Bon ok, admettons qu'on veuille tester si oui ou non il est nécessaire de réécrire le fichier hosts. Tu n'as pas besoin de faire un tableau @ipadresses pour collecter les adresses ip ! Les adresses IPs déjà rencontrées à ce stade sont les clefs de ton hash. Il suffit de vérifier si la clef (la nouvelle IP) existe: if ( exists $hashIPv4Hosts{$ipentry} ) { ... et bye bye @ipadresses et le vilain smartmatch.

    Et plus tard, au lieu de foreach my $ipaddress (@ipaddresses) { tu boucles sur les clefs du hash: foreach my $ipaddress (keys %hashIPv4Hosts) { (au passage, remarque que l'ensemble des clefs d'un hash est un tableau, et que c'est la raison pour laquelle j'ai opté dans mon code pour un hash de hashs avec 1 comme valeur bidon, tout est dans les clefs).

    À propos de split(/\s+|\t/....: La classe de caractères \s contient déjà la tabulation donc split(/\s+/.... revient au même. Mieux encore, si on passe à split une chaîne d'un espace, il comprend tout seul comme un grand qu'il faut découper là où il y a des caractères blancs quelque soit leur nature ou nombre et ce sans créer de parties vides. Malin lapin, habile crocodile. split(' ', ....

    D'une manière générale tu crées trop de variables et tu n'exploites jamais le contexte et $_. Au cours de tes pérégrination au pays des références et des structures complexes, n'hésites pas à faire un détour du coté de l'autovivification, cela te sera utile.

    Bon courage.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  11. #11
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui, je me suis un peu pris la tête... et j'ai lu que le smartmatch n'est pas du goût de tout le monde... dans ce cas-ci je le trouve plutôt pratique... même s'il est certain qu'en Perl il soit possible de faire la même chose sans (exists semble déjà très élaboré).
    Je suis en vacances et du coup je vais bouquiner et me renforcer en Perl.

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/10/2017, 11h59
  2. [MySQL] Concept d'un script pour chercher des villes ou des régions (A la Google Map)
    Par cool-man dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 31/08/2010, 10h29
  3. Script pour modifier fichier "host"
    Par chuispasla dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 05/08/2009, 14h03
  4. [langage] perl script pour balancer un B-arbre
    Par RonMaster dans le forum Langage
    Réponses: 5
    Dernier message: 22/10/2004, 17h35
  5. Script pour envoyer des info a mysql
    Par rhum1 dans le forum Linux
    Réponses: 6
    Dernier message: 15/04/2003, 16h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo