Ответ 1
Вы можете использовать grep, чтобы вытащить их.
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
Как извлечь текстовую часть с помощью регулярных выражений в оболочке Linux? Допустим, у меня есть файл, где в каждой строке указан IP-адрес, но в другой позиции. Какой самый простой способ извлечь эти IP-адреса, используя обычные инструменты командной строки Unix?
Вы можете использовать grep, чтобы вытащить их.
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
Большинство примеров здесь будут соответствовать 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, если вы хотите увидеть всю строку, которая соответствует.
Обычно я начинаю с 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)
Это работает отлично для меня в журналах доступа.
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}'
где '^' - это якорь, который сообщает, чтобы искать в начале строки.
Я написал немного script, чтобы лучше видеть мои файлы журналов, это ничего особенного, но может помочь многим людям, которые обучение perl. Он выполняет поиск DNS по IP-адресам после их извлечения.
Я написал информативную статью в блоге на эту тему: Как извлечь 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):
Если вы хотите, вы можете проверить регулярное выражение IPv4 здесь.
Вы можете использовать некоторый помощник оболочки, который я сделал: 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
grep -E -o "([0-9] {1,3} [.]) {3} [0-9] {1,3}"
Вы можете использовать sed. Но если вы знаете perl, это может быть проще и более полезно знать в долгосрочной перспективе:
perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
Для тех, кто хочет получить готовое решение для получения 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
Хороший способ запретить хакеров. Далее вы можете:
deny from
и пробел в начале каждой строкиЯ бы предложил perl. (\ d +.\d +.\d +.\d +), вероятно, должен сделать трюк.
EDIT: чтобы сделать его более похожим на полную программу, вы можете сделать что-то вроде следующего (не тестировалось):
#!/usr/bin/perl -w
use strict;
while (<>) {
if (/(\d+\.\d+\.\d+\.\d+)/) {
print "$1\n";
}
}
Это обрабатывает один IP-адрес. Если у вас более одного IP-адреса в строке, вам нужно использовать опцию /g. man perlretut дает вам более подробное руководство по регулярным выражениям.
Вы также можете использовать awk. Что-то вроде...
awk '{i = 1; if (NF > 0) do {if ($ я ~/regexp/) print $i; я ++;} while (i <= NF);} 'file
- может потребоваться очистка. просто быстрый и грязный ответ, чтобы показать в основном, как это сделать с awk
Все предыдущие ответы имеют одну или несколько проблем. Принимаемый ответ позволяет номерам 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
Прокомментируйте, если в этом регулярном выражении все еще есть проблемы. Легко найти много неправильного регулярного выражения для этой проблемы, я надеюсь, что у этого нет реальных проблем.
Все здесь используют действительно длинные регулярные выражения, но на самом деле понимание регулярного выражения POSIX позволит вам использовать небольшую команду grep
подобную этой, для печати IP-адресов.
grep -Eo "(([0-9]{1,3})\.){3}([0-9]{1,3})"
(Примечание) Это не игнорирует недействительные IP-адреса, но это очень просто.
Я перепробовал все ответы, но у всех них была одна или несколько проблем, и я перечислил некоторые из них.
123.456.789.111
как действительный IP127.0.00.1
действительным IP08.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)
Я хотел получить только IP-адреса, которые начинаются с "10", из любого файла в каталоге:
grep -o -nr "[10]\{2\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" /var/www
Если вам не указан конкретный файл, и вам нужно извлечь IP-адрес, нам нужно сделать это рекурсивно. grep command → Ищет текст или файл для соответствия данной строке и отображает согласованную строку.
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 → Мы можем выполнить поиск всего дерева каталогов, то есть текущего каталога и всех уровней подкаталогов. Он обозначает рекурсивный поиск.
-o → Печать только соответствующей строки
-E → Использовать расширенное регулярное выражение
Если бы мы не использовали вторую команду grep после этого канала, мы получили бы IP-адрес вместе с тем путем, в котором он присутствует.
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\}$'
Предположим, что файл разделен запятой и позиция ip-адреса в начале, в конце и где-то посередине
Первое регулярное выражение ищет точное соответствие ip-адреса в начале строки. Второе регулярное выражение после или ищет ip-адрес в середине. Мы сопоставляем его таким образом, что число, которое следует за ним, должно быть от 1 до 3 цифр .falsy ips, как 12345.12.34.1, может быть исключено в этом.
Третий regexp ищет ip-адрес в конце строки
для centos6.3
ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | awk 'BEGIN {FS=":"} {print $2}'