it-roy-ru.com

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

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

56
Kazimieras Aliulis

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

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

Большинство примеров здесь будут соответствовать 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, если вы хотите увидеть всю строку, которая соответствует.

40
Sarel Botha

Я обычно начинаю с 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
JB.

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

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}'

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

10
Sankalp

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

3
James

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

В этой статье есть подробное руководство по наиболее распространенным различным шаблонам для IP-адресов, которые часто необходимо извлечь и изолировать от простого текста с помощью регулярных выражений.
Это руководство основано на инструменте CodVerter IP Extractor source source для обработки извлечения и обнаружения 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-адреса с помощью Prefix («косая нотация»):

\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
jonathana

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

2
shaa0601

Вы можете использовать помощника Shell, который я сделал: 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) из Shell:

$. ipextract

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

$ ipextract < /etc/hosts
127.0.0.1
255.255.255.255
$

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

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

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

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

Вы также можете использовать awk. Что-то вроде ...

awk '{i = 1; if (NF> 0) do {if ($ i ~/regexp /) print $ i; i ++;} while (i <= NF);} 'файл

- может потребоваться очистка. просто быстрый и грязный ответ, чтобы показать, как это сделать с помощью awk

0
Allen Ratcliff

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

  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)
0
Mohsen Sarkar

Все предыдущие ответы имеют одну или несколько проблем. Принятый ответ позволяет IP-номера, такие как 999.999.999.999. В настоящее время второй по популярности ответ требует префикса с 0, например 127.000.000.001 или 008.008.008.008 вместо 127.0.0.1 или 8.8.8.8. У Apama это почти правильно, но это выражение требует, чтобы ipnumber был единственным в строке, без начального или конечного пробела, и при этом он не мог выбирать ip из середины строки.

Я думаю, что правильное регулярное выражение можно найти на http://www.regextester.com/22

Поэтому, если вы хотите извлечь все ip-адреса из файла, используйте:

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

Если вы не хотите использовать дубликаты, используйте:

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

Пожалуйста, прокомментируйте, если в этом регулярном выражении все еще есть проблемы. Легко найти много неправильных регулярных выражений для этой проблемы, я надеюсь, что у этого нет реальных проблем.

0
anneb

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

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

(Примечание.). Это не игнорирует недействительные IP-адреса, но это очень просто.

0
Yokai

Для тех, кто хочет получить готовое решение для получения IP-адресов из журнала Apache и перечисления случаев, когда IP-адрес посещал веб-сайт, используйте эту строку:

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

Хороший способ запретить хакеров. Далее вы можете:

  1. Удалить строки менее чем за 20 посещений
  2. Используя регулярное выражение, вырежьте до одного пробела, так что у вас будут только IP-адреса
  3. Используя regexp, вырежьте 1-3 последние цифры IP-адресов, чтобы у вас были только сетевые адреса
  4. Добавьте deny from и пробел в начале каждой строки
  5. Поместите файл результатов как .htaccess
0
pbies

Я бы предложил Perl. (\ d +.\d +.\d +.\d +), вероятно, добьется цели. 

Правка: просто чтобы сделать его более похожим на законченную программу, вы можете сделать что-то вроде следующего (не проверено): 

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

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

Это обрабатывает один IP на линию. Если у вас более одного IP-адреса в строке, вам нужно использовать параметр/g. man perlretut дает вам более подробное руководство по регулярным выражениям. 

0
PolyThinker