Как вы извлекаете IP-адреса из файлов, используя регулярные выражения в оболочке Linux? - PullRequest
56 голосов
/ 09 января 2009

Как извлечь текстовую часть с помощью регулярных выражений в оболочке Linux? Допустим, у меня есть файл, где в каждой строке указан IP-адрес, но в другой позиции. Какой самый простой способ извлечь эти IP-адреса, используя обычные инструменты командной строки Unix?

Ответы [ 18 ]

112 голосов
/ 09 января 2009

Вы можете использовать grep , чтобы вытащить их.

grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
41 голосов
/ 09 января 2009

Большинство примеров здесь будут соответствовать 999.999.999.999, который технически не является действительным IP-адресом.

Следующие параметры будут соответствовать только действительным IP-адресам (включая сетевые и широковещательные адреса).

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

Опустите -o, если вы хотите увидеть всю строку, которая соответствует.

11 голосов
/ 09 января 2009

Обычно я начинаю с grep, чтобы получить правильное регулярное выражение.

# [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

Тогда я бы попытался преобразовать его в sed, чтобы отфильтровать остальную часть строки. (Прочитав эту ветку, мы с тобой больше не будем этого делать: вместо этого мы будем использовать grep -o)

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

Именно тогда меня обычно раздражает sed за то, что я не использую те же регулярные выражения, что и остальные. Поэтому я перехожу на perl.

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

Perl приятно знать в любом случае. Если у вас установлен небольшой CPAN, вы даже можете сделать его более надежным при небольших затратах:

$ perl -MRegexp::Common=net -nE '/$RE{net}{IPV4}/ and say $&' file(s)
11 голосов
/ 29 августа 2014

Это нормально работает для меня в журналах доступа.

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

Давайте разберем его по частям.

  • [0-9]{1,3} означает от одного до трех вхождений диапазона, указанного в []. В этом случае это 0-9. поэтому он соответствует шаблонам, таким как 10 или 183.

  • С последующим символом «.». Нам нужно будет избежать этого как '.' является метасимволом и имеет особое значение для оболочки.

Так что теперь мы находимся в паттернах типа «123.» '12 «. и т.д.

  • Этот шаблон повторяется три раза (с «.»). Поэтому мы заключаем его в скобки. ([0-9]{1,3}\.){3}

  • И, наконец, шаблон повторяется, но на этот раз без «.». Вот почему мы держали это отдельно на третьем этапе. [0-9]{1,3}

Если ips находятся в начале каждой строки, как в моем случае, используйте:

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

где '^' - это якорь, который указывает на поиск в начале строки.

3 голосов
/ 14 января 2011

Я написал небольшой скрипт , чтобы лучше видеть мои файлы журналов, в этом нет ничего особенного, но он может помочь многим людям, изучающим Perl. Он выполняет поиск DNS по IP-адресам после их извлечения.

3 голосов
/ 06 января 2019

Я написал информативную статью в блоге на эту тему: Как извлечь IPv4 и IPv6 IP-адреса из обычного текста с помощью Regex .

В статье приведено подробное руководство по наиболее распространенным различным шаблонам для IP-адресов, которые часто необходимо извлекать и изолировать от простого текста с помощью регулярных выражений.
Это руководство основано на инструменте исходного кода CodVerter IP Extractor для обработки извлечения и обнаружения IP-адресов при необходимости.

Если вы хотите проверить и захватить IPv4-адрес, этот шаблон может выполнить работу:

\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

или для проверки и захвата IPv4-адреса с префиксом («косая черта»):

\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

или для захвата маски подсети или маски:

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

или чтобы отфильтровать адреса маски подсети, вы делаете это с помощью регулярного выражения отрицательный взгляд :

\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

Для проверки IPv6 вы можете перейти по ссылке на статью, которую я добавил в верхней части этого ответа.
Вот пример для захвата всех распространенных шаблонов (взят из примера справки CodVerter IP Extractor):

enter image description here

Если вы хотите, вы можете проверить регулярное выражение IPv4 здесь .

2 голосов
/ 14 февраля 2015

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

2 голосов
/ 23 февраля 2014

Вы можете использовать некоторый помощник по оболочке, который я сделал: https://github.com/philpraxis/ipextract

включены сюда для удобства:

#!/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,}' 
}

Загрузите его / загрузите (если он хранится в файле ipextract) из оболочки:

$. ipextract

Используйте их:

$ ipextract < /etc/hosts
127.0.0.1
255.255.255.255
$

Для примера реального использования:

ipextractfqdn < /var/log/snort/alert | sort -u
dmesg | ipextractudp
1 голос
/ 09 января 2009

Вы можете использовать sed . Но если вы знаете Perl, это может быть проще и полезнее узнать в долгосрочной перспективе:

perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
0 голосов
/ 13 марта 2018

Я перепробовал все ответы, но у всех них была одна или несколько проблем, и я перечислил несколько из них.

  1. Некоторые обнаружены 123.456.789.111 как действительный IP
  2. Некоторые не распознают 127.0.00.1 как действительный IP
  3. Некоторые не обнаруживают IP-адреса, начинающиеся с нуля, например 08.8.8.8

Так что здесь я публикую регулярное выражение, которое работает на всех вышеперечисленных условиях.

Примечание: я извлек более 2 миллионов IP без каких-либо проблем со следующим регулярным выражением.

(?:(?: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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...