web-dev-qa-db-fra.com

Comment extraire les adresses IP des fichiers en utilisant une expression régulière dans un shell linux?

Comment extraire une partie de texte par expression rationnelle dans un shell linux? Disons que j'ai un fichier où chaque ligne est une adresse IP, mais à une position différente. Quel est le moyen le plus simple d'extraire ces adresses IP à l'aide d'outils de ligne de commande unix courants?

56
Kazimieras Aliulis

Vous pouvez utiliser grep pour les extraire.

grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
112
brien

La plupart des exemples ici correspondront à 999.999.999.999 qui n'est pas techniquement une adresse IP valide.

Les éléments suivants ne concordent qu'avec les adresses IP valides (y compris les adresses réseau et de diffusion).

grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt

Omettez le -o si vous voulez voir toute la ligne qui correspond.

40
Sarel Botha

Je commence habituellement par grep, pour obtenir l'expression rationnelle correcte.

# [multiple failed attempts here]
grep    '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'                 file  # good?
grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' file  # good enough

Ensuite, j'essayerais de le convertir en sed pour filtrer le reste de la ligne. (Après avoir lu ce fil de discussion, vous et moi n'allons plus le faire: nous allons utiliser grep -o à la place)

sed -ne 's/.*\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\).*/\1/p  # FAIL

C'est à ce moment-là que je m'énerve généralement avec sed pour ne pas utiliser les mêmes expressions rationnelles que quiconque. Je passe donc à Perl.

$ Perl -nle '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ and print $&'

Perl est bon à savoir dans tous les cas. Si vous avez un petit morceau de CPAN installé, vous pouvez même le rendre plus fiable à moindre coût:

$ Perl -MRegexp::Common=net -nE '/$RE{net}{IPV4}/ and say $&' file(s)
11
JB.

Cela fonctionne bien pour moi dans les journaux d'accès.

cat access_log | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}'

Brisons-le partie par partie.

  • [0-9]{1,3} signifie une à trois occurrences de la plage mentionnée dans []. Dans ce cas, il est 0-9. il correspond donc à des motifs tels que 10 ou 183.

  • Suivi d'un '.' Nous devrons échapper à cela en tant que '.' est un méta-caractère et a une signification particulière pour Shell.

Alors maintenant, nous sommes à des modèles comme «123». '12. ' etc.

  • Ce motif se répète trois fois (avec le '.'). Donc nous le mettons entre parenthèses .([0-9]{1,3}\.){3}

  • Et enfin le motif se répète mais cette fois sans le '.'. C'est pourquoi nous l'avons gardé séparément dans la 3ème étape. [0-9]{1,3}

Si les ips sont au début de chaque ligne comme dans mon cas, utilisez:

egrep -o '^([0-9]{1,3}\.){3}[0-9]{1,3}'

où '^' est une ancre qui indique de rechercher en début de ligne.

10
Sankalp

J'ai écrit un peu script pour mieux voir mes fichiers de log, ce n'est pas spécial, mais cela pourrait aider beaucoup de gens qui apprennent Perl. Il effectue des recherches DNS sur les adresses IP après les avoir extraites. 

3
James

J'ai écrit un article de blog informatif sur ce sujet: Comment extraire des adresses IP IPv4 et IPv6 d'un texte brut à l'aide de Regex .

Dans cet article, vous trouverez un guide détaillé des différents modèles les plus courants pour les IP, qui doivent souvent être extraits et isolés du texte brut à l'aide d'expressions régulières.
Ce guide est basé sur l'outil de code source IP Extractor de CodVerter permettant de gérer l'extraction et la détection d'adresses IP si nécessaire .

Si vous souhaitez valider et capturer l'adresse IPv4, ce modèle peut faire l'affaire:

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

ou pour valider et capturer une adresse IPv4 avec Prefix ("notation par barre oblique"):

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?/[0-9]{1,2})\b

ou pour capturer un masque de sous-réseau ou un masque générique:

(255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)

ou pour filtrer les adresses de masque de sous-réseau vous le faites avec regex lookahead négatif :

\b((?!(255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)))(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

Pour la validation IPv6, vous pouvez aller au lien d'article que j'ai ajouté en haut de cette réponse.
Voici un exemple pour capturer tous les modèles courants (extraits de l'exemple d'aide de CodVerter sur IP Extractor):

 enter image description here

Si vous le souhaitez, vous pouvez tester la regex IPv4 ici .

2
jonathana

grep -E -o "([0-9] {1,3} [.]) {3} [0-9] {1,3}"

2
shaa0601

Vous pouvez utiliser l’assistant Shell que j’ai fabriqué: https://github.com/philpraxis/ipextract

inclus ici pour plus de commodité:

#!/bin/sh
ipextract () 
{ 
egrep --only-matching -E  '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' 
}

ipextractnet ()
{ 
egrep --only-matching -E  '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[[:digit:]]+' 
}

ipextracttcp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/tcp' 
}

ipextractudp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/udp' 
}

ipextractsctp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/sctp' 
}

ipextractfqdn ()
{ 
egrep --only-matching -E  '[a-zA-Z0-9]+[a-zA-Z0-9\-\.]*\.[a-zA-Z]{2,}' 
}

Chargez-le/source-le (lorsqu'il est stocké dans un fichier ipextract) à partir de Shell:

$. ipextract

Utilise les:

$ ipextract < /etc/hosts
127.0.0.1
255.255.255.255
$

Pour quelques exemples d'utilisation réelle:

ipextractfqdn < /var/log/snort/alert | sort -u
dmesg | ipextractudp
2
Phil L.

Vous pouvez utiliser sed . Mais si vous connaissez Perl, cela pourrait être plus facile et plus utile de savoir à long terme:

Perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
1
Avi

Vous pouvez aussi utiliser awk. Quelque chose comme ...

awk '{i = 1; if (NF> 0) fait {if ($ i ~/regexp /) print $ i; i ++;} while (i <= NF);} 'fichier

- peut avoir besoin de nettoyage. juste une réponse rapide et sale pour montrer fondamentalement comment le faire avec awk

0
Allen Ratcliff

J'ai essayé toutes les réponses mais toutes ont eu un ou plusieurs problèmes et j'en ai énuméré quelques-unes.

  1. Certains ont détecté 123.456.789.111 comme IP valide 
  2. Certains ne détectent pas 127.0.00.1 comme IP valide 
  3. Certains ne détectent pas les adresses IP commençant par zéro comme 08.8.8.8

Donc ici je poste une regex qui fonctionne dans toutes les conditions ci-dessus. 

Note: J'ai extrait plus de 2 millions d'IP sans aucun problème avec les expressions régulières suivantes.

(?:(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)\.){3}(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)
0
Mohsen Sarkar

Toutes les réponses précédentes ont un ou plusieurs problèmes. La réponse acceptée autorise les numéros IP tels que 999.999.999.999. La deuxième réponse la plus votée actuellement nécessite de préfixer 0, par exemple 127.000.000.001 ou 008.008.008.008 au lieu de 127.0.0.1 ou 8.8.8.8. Apama a presque tout à fait raison, mais cette expression nécessite que l'ipnumber soit la seule chose sur la ligne, aucun espace de début ou de fin n'est autorisé, pas plus qu'il ne peut sélectionner d'ip au milieu d'une ligne.

Je pense que la bonne expression rationnelle peut être trouvée sur http://www.regextester.com/22

Donc, si vous voulez extraire toutes les adresses IP d'un fichier, utilisez:

grep -Eo "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" file.txt

Si vous ne voulez pas de doublons, utilisez:

grep -Eo "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" file.txt | sort | uniq

Veuillez commenter s'il y a encore des problèmes dans cette regex. Il est facile de trouver beaucoup de mauvaises expressions rationnelles pour ce problème, j'espère que celui-ci n'a pas de problèmes réels.

0
anneb

Tout le monde ici utilise des expressions régulières très longues, mais comprendre réellement l'expression régulière de POSIX vous permettra d'utiliser une petite commande grep comme celle-ci pour imprimer les adresses IP.

grep -Eo "(([0-9]{1,3})\.){3}([0-9]{1,3})"

(Note latérale) Cela n'ignore pas les IP invalides, mais c'est très simple.

0
Yokai

Pour ceux qui veulent une solution prête pour obtenir les adresses IP à partir du journal Apache et répertoriant le nombre de fois où l'adresse IP a visité le site Web, utilisez cette ligne:

grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' error.log | sort | uniq -c | sort -nr > occurences.txt

Belle méthode pour interdire les pirates. Ensuite, vous pouvez:

  1. Supprimer les lignes avec moins de 20 visites
  2. Utiliser l'expression rationnelle coupée jusqu'à un seul espace pour ne conserver que les adresses IP
  3. En utilisant l'expression rationnelle, coupez de 1 à 3 les derniers numéros d'adresses IP de sorte que vous n'ayez que des adresses réseau.
  4. Ajoutez deny from et un espace au début de chaque ligne
  5. Mettre le fichier de résultat en tant que .htaccess
0
pbies

Je suggérerais Perl. (\ d +.\d +.\d +.\d +) devrait probablement faire l'affaire. 

EDIT: Juste pour que cela ressemble plus à un programme complet, vous pourriez faire quelque chose comme ceci (non testé): 

#!/usr/bin/Perl -w
use strict;

while (<>) {
    if (/(\d+\.\d+\.\d+\.\d+)/) {
        print "$1\n";
    }
}

Cela gère une adresse IP par ligne. Si vous avez plusieurs adresses IP par ligne, vous devez utiliser l'option/g. man perlretut vous fournit un didacticiel plus détaillé sur les expressions régulières. 

0
PolyThinker