Вопрос или проблема
Я хочу извлечь IPv6-адреса из файлов журнала, которые содержат только действительные IPv6-адреса, с которых кто-то подключился (а также содержат строки с IPv4 и многие другие строки без каких-либо IP, например, /var/log/secure).
Поэтому для этого регулярного выражения не так важно соответствовать только истинным действительным IPv6 согласно RFC, как это делают огромные регулярные выражения с https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses, но оно должно соответствовать всему, что хоть как-то напоминает IPv6, чтобы не выдавало слишком много ложных срабатываний, и должно быть как можно короче, чтобы его было легко запомнить и вводить.
Для быстрого ответа я бы сказал:
egrep "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?"
но вы должны предполагать, что адрес содержит как минимум две ‘секции’, например:
ff00:3456::
или ff00::3456
, вот это: ff00::
не будет найдено.
Другим решением, которое я нашел, является это регулярное выражение:
^(\:\:)?[0-9a-fA-F]{1,4}(\:\:?[0-9a-fA-F]{1,4}){0,7}(\:\:)?$
но это приведет к ложным срабатываниям, таким как строки ‘aaaa’, ‘abc’, поэтому должна быть дополнительная проверка, такая как:
`^.*\:.*\:.*$`
В этом случае фрагмент bash-скрипта выглядит так:
if [[ "$col" =~ ^(\:\:)?[0-9a-fA-F]{1,4}(\:\:?[0-9a-fA-F]{1,4}){0,7}(\:\:)?$ ]] && \
[[ "$col" =~ ^.*\:.*\:.*$ ]] ; then
echo "Совпадение IPv6"
else
echo "Нет совпадения"
fi
это для проверки, представляет ли $col
IPv6 или нет. Здесь вам нужно будет разработать код, чтобы сначала разбить запись журнала на секции.
Ответ или решение
Для извлечения IPv6-адресов из лог-файлов, таких как /var/log/secure, можно использовать регулярные выражения различной сложности. В вашем случае, так как важно лишь извлечение адресов, которые хотя бы напоминают IPv6, можно предложить более простое и краткое регулярное выражение.
Вот одно из простых вариантов регулярного выражения для grep:
egrep -o "([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}|::"
Объяснение:
([0-9a-fA-F]{1,4}:){1,7}
: Это часть соответствует от одной до семи групп, содержащих от 1 до 4 шестнадцатеричных символов, за которыми следует двоеточие. Это соответствует форматам частей IPv6-адреса.[0-9a-fA-F]{1,4}
: Последняя часть соответствует одной части, которая содержит от 1 до 4 шестнадцатеричных символов.|::
: Это соответствует краткому представлению IPv6-адреса, где используются двойные двоеточия для обозначения последовательности нулевых частей.
Вышеуказанное выражение будет захватывать как полные, так и краткие формы IPv6-адресов, но также будут захватываться строки, которые не являются действительными адресами. Для уменьшения вероятности получения ложных срабатываний, можно дополнительно использовать фильтрацию, проверяя наличие хотя бы двух двоеточий в строке.
Пример использования в bash:
Вот пример кода, который проверит, содержит ли строка действительный IPv6-адрес:
while read -r line; do
if [[ "$line" =~ ([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}|:: ]] && \
[[ "$line" =~ [a-fA-F0-9]:.*:.* ]]; then
echo "Найден IPv6 адрес: $line"
fi
done < /var/log/secure
Объяснение кода:
while read -r line; do
: Читает строки из файла.[[ "$line" =~ ... ]]
: Проверяет строку на совпадение с регулярным выражением для IPv6.[[ "$line" =~ [a-fA-F0-9]:.*:.* ]]
: Убеждается, что в строке содержатся хотя бы две части адреса, разделенные двоеточием.echo "Найден IPv6 адрес: $line"
: Если обе проверки успешны, строка считается содержащей IPv6-адрес.
Это решение должно эффективно помогать в нахождении IPv6-адресов в логах, позволяя при этом исключить ложные срабатывания относительно некорректных строк.