Comment extraire les adresses IP des fichiers en utilisant une regex dans un shell Linux?

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

Vous pouvez utiliser grep pour les retirer.

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

La plupart des exemples présentés ici correspondent à 999.999.999.999, qui ne constitue pas techniquement une adresse IP valide.

Les éléments suivants correspondent uniquement aux 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 souhaitez voir la ligne complète correspondant.

Je commence habituellement par grep, pour obtenir le regexp correct.

 # [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, je vais essayer de le convertir en sed pour filtrer le rest de la ligne. (Après avoir lu ce fil de discussion, vous et moi ne ferons plus cela: nous allons plutôt utiliser grep -o )

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

C’est quand je suis généralement ennuyé avec sed pour ne pas utiliser les mêmes regexes 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 bout 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) 

Cela fonctionne bien pour moi dans les journaux d’access.

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

Disons-le en 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 modèles comme 10 ou 183.

  • Suivi d’un ‘.’. Nous devrons y échapper comme “.” est un méta caractère et a une signification particulière pour le shell.

Alors maintenant, nous sums à 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 conservé 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 dit de rechercher au début d’une ligne.

J’ai écrit un petit script pour voir mes fichiers journaux mieux, rien de spécial, mais cela pourrait aider beaucoup de gens qui apprennent perl. Il effectue des recherches DNS sur les adresses IP après leur extraction.

Vous pouvez utiliser un assistant de shell que j’ai créé: https://github.com/philpraxis/ipextract

les 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 / sourcez-le (lorsqu’il est stocké dans le fichier ipextract) à partir du shell:

$. ipextract

Utilise les:

 $ ipextract < /etc/hosts 127.0.0.1 255.255.255.255 $ 

Pour un exemple d'utilisation réelle:

 ipextractfqdn < /var/log/snort/alert | sort -u dmesg | ipextractudp 

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

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

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

Je suggère perl. (\ d +. \ d +. \ d +. \ d +) devrait probablement faire l’affaire.

EDIT: Juste pour faire plus comme un programme complet, vous pourriez faire quelque chose comme ce qui suit (non testé):

 #!/usr/bin/perl -w use ssortingct; while (<>) { if (/(\d+\.\d+\.\d+\.\d+)/) { print "$1\n"; } } 

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

Vous pouvez également utiliser awk. Quelque chose comme …

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

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

Toutes les réponses précédentes ont un ou plusieurs problèmes. La réponse acceptée permet des numéros IP comme 999.999.999.999. La seconde réponse actuellement la plus populaire exige le préfixe 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 raison, mais cette expression exige que l’ipnumber soit la seule chose sur la ligne, aucun espace de début ou de fin n’est autorisé, et il ne peut pas non plus sélectionner ip à partir du milieu d’une ligne.

Je pense que le regex correct peut être trouvé 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 

S’il vous plaît commenter s’il y a encore des problèmes dans cette regex. Il est facile de trouver beaucoup de regex incorrectes pour ce problème, j’espère que celui-ci n’a pas de vrais problèmes.

J’ai essayé toutes les réponses mais tous avaient un ou plusieurs problèmes que j’en énumère quelques-uns.
1.Quelques détectés 123.456.789.111 comme adresse IP valide
2. Certains ne détectent pas 127.0.00.1 comme adresse IP valide
3. Certains ne détectent pas les adresses IP commençant par zéro comme 08.8.8.8

Donc, voici une regex qui fonctionne sur toutes les conditions ci-dessus.

Remarque: J’ai extrait plus de 2 millions d’IP sans aucun problème avec la regex suivante.

 (?:(?: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) 

Tout le monde ici utilise des expressions régulières très longues, mais en fait, comprendre la regex 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})" 

(Side note) Cela n’ignore pas les adresses IP invalides mais c’est très simple.

Si vous ne recevez pas de fichier spécifique et que vous devez extraire une adresse IP, nous devons le faire récursivement. Commande grep -> Recherche un texte ou un fichier pour rechercher une chaîne donnée et affiche la chaîne correspondante.

grep -roE ‘[0-9] {1,3}. [0-9] {1,3}. [0-9] {1,3}. [0-9] {1,3}’ | grep -oE ‘[0-9] {1,3}. [0-9] {1,3}. [0-9] {1,3}. [0-9] {1,3}’

-r -> Nous pouvons effectuer des recherches dans l’ensemble de l’arborescence des répertoires, c’est-à-dire le répertoire en cours et tous les niveaux des sous-répertoires. Cela dénote une recherche récursive.

-o -> Imprimer uniquement la chaîne correspondante

-E -> Utiliser des expressions régulières étendues

Si nous n’avions pas utilisé la deuxième commande grep après le tube, nous aurions l’adresse IP avec le chemin d’access où elle se trouve

 cat ip_address.txt | grep '^[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[,].*$\|^.*[,][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[,].*$\|^.*[,][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}$' 

Supposons que le fichier est délimité par des virgules et la position de l’adresse IP au début, à la fin et quelque part au milieu

Première expression rationnelle recherche la correspondance exacte de l’adresse IP au début de la ligne. La deuxième expression rationnelle après le ou recherche une adresse IP au milieu. Nous la comparons de telle manière que le nombre qui suit devrait être exactement de 1 à 3 chiffres. Les fausses ips comme 12345.12.34.1 peuvent être exclues.

La troisième expression rationnelle recherche l’adresse IP à la fin de la ligne

pour centos6.3

ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | awk 'BEGIN {FS=":"} {print $2}'