Проверка адресов IPv4 с помощью regexp
Я пытался получить эффективное регулярное выражение для проверки IPv4, но без особого успеха. В какой-то момент мне показалось, что с меня хватит!--1-->, но это дает некоторые странные результаты:
[chris@helios bashscripts]$ grep --version
grep (GNU grep) 2.7
[chris@helios bashscripts]$ grep -E 'b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(.|$)){4}b' <<< 192.168.1.1
192.168.1.1
[chris@helios bashscripts]$ grep -E 'b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(.|$)){4}b' <<< 192.168.1.255
192.168.1.255
[chris@helios bashscripts]$ grep -E 'b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(.|$)){4}b' <<< 192.168.255.255
[chris@helios bashscripts]$ grep -E 'b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(.|$)){4}b' <<< 192.168.1.2555
192.168.1.2555
Я сделал поиск, чтобы узнать, было ли это уже задано и ответили, но другие ответы, похоже, просто показывают, как определить 4 группы из 1-3 чисел или не работают для меня.
какие идеи? Спасибо!
26 ответов
у вас уже есть рабочий ответ, но на всякий случай вам интересно, что было не так с вашим оригинальным подходом, ответ заключается в том, что вам нужны круглые скобки вокруг вашего чередования в противном случае (\.|$)
требуется, только если число меньше 200.
'\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\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]?)$
принимать:
127.0.0.1
192.168.1.1
192.168.1.255
255.255.255.255
0.0.0.0
1.1.1.01
отклонение:
30.168.1.255.1
127.1
192.168.1.256
-1.2.3.4
3...3
попробуйте онлайн с модульными тестами:https://www.debuggex.com/r/-EDZOqxTxhiTncN6/1
Regex не является инструментом для этой работы. Лучше было бы написать парсер, который отделяет четыре числа и проверяет, что они находятся в диапазоне [0,255]. Нефункциональные тестирую уже нечитаю!
IPv4-адрес (точный захват) Матчи 0.0.0.0 по 255.255.255.255 Используйте это регулярное выражение для сопоставления IP-номеров с точностью. Каждый из 4 номеров хранится в группе захвата, так что вы можете получить к ним доступ для дальнейшей обработки.
\b
(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]?)
\b
взято из библиотеки Jgsoft RegexBuddy
Edit: это (\.|$)
часть кажется wierd
Я искал что - то подобное для IPv4-адресов-регулярное выражение, которое также прекратило проверку часто используемых частных ip-адресов (192.168.X. y, 10.х.г.з 172.16.X. y) так использовал отрицательный взгляд aheads для достижения этого:
(?!(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.).*)
(?!255\.255\.255\.255)(25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[1-9])
(\.(25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|\d)){3}
(Они должны быть на одной строке, конечно, отформатированы для целей удобочитаемости на 3 отдельных строках)
Он не может быть оптимизирован для скорости, но работает хорошо, если только ищу "реальные" интернет-адреса.
вещи, которые будут (и должны) не выполнено:
0.1.2.3 (0.0.0.0/8 is reserved for some broadcasts)
10.1.2.3 (10.0.0.0/8 is considered private)
172.16.1.2 (172.16.0.0/12 is considered private)
172.31.1.2 (same as previous, but near the end of that range)
192.168.1.2 (192.168.0.0/16 is considered private)
255.255.255.255 (reserved broadcast is not an IP)
.2.3.4
1.2.3.
1.2.3.256
1.2.256.4
1.256.3.4
256.2.3.4
1.2.3.4.5
1..3.4
IPs, которые будут (и должны) работать:
1.0.1.0 (China)
8.8.8.8 (Google DNS in USA)
100.1.2.3 (USA)
172.15.1.2 (USA)
172.32.1.2 (USA)
192.167.1.2 (Italy)
при условии, если кто-то еще ищет проверку "Интернет-IP-адреса, не включая общие частные адреса"
новая и улучшенная более короткая версия
^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(?!$)|$)){4}$
он использует отрицательный lookahead (?!)
чтобы удалить случай, когда ip может закончиться .
ответ
^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}
(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$
Я думаю, что это самое точное и строгое регулярное выражение, оно не принимает такие вещи, как 000.021.01.0.
похоже, что большинство других ответов здесь делают и требуют дополнительного регулярного выражения для отклонения случаев, подобных этому-т. е. 0
начальные номера и ip, который заканчивается .
Это немного дольше, чем некоторые, но это то, что я использую для сопоставления адресов IPv4. Просто без компромиссов.
^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$
мне удалось построить регулярное выражение из всех других ответов.
(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}
С маской подсети :
^$|([01]?\d\d?|2[0-4]\d|25[0-5])\
.([01]?\d\d?|2[0-4]\d|25[0-5])\
.([01]?\d\d?|2[0-4]\d|25[0-5])\
.([01]?\d\d?|2[0-4]\d|25[0-5])
((/([01]?\d\d?|2[0-4]\d|25[0-5]))?)$
const char*ipv4_regexp = "\b(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]?)\b";
я адаптировал регулярное выражение, взятое из библиотеки Jgsoft RegexBuddy, к языку C (regcomp / regexec), и я узнал, что он работает, но в некоторых ОС, таких как Linux, есть небольшая проблема. Это регулярное выражение принимает IPv4-адрес, такой как 192.168.100.009, где 009 в Linux считается восьмеричным значением, поэтому адрес не тот, который вы думали. Я изменил регулярное выражение следующим образом:
const char* ipv4_regex = "\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\b";
использование этого обычного expressione теперь 192.168.100.009 недопустимо IPv4-адрес, хотя 192.168.100.9 ОК.
Я также изменил регулярное выражение для многоадресного адреса, и это следующее:
const char* mcast_ipv4_regex = "\b(22[4-9]|23[0-9])\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]?)\."
"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\b";
Я думаю, вам нужно адаптировать регулярное выражение к языку, который вы используете для разработки своего приложения
Я привел пример на java:
package utility;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NetworkUtility {
private static String ipv4RegExp = "\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d?)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d?)\b";
private static String ipv4MulticastRegExp = "2(?:2[4-9]|3\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)){3}";
public NetworkUtility() {
}
public static boolean isIpv4Address(String address) {
Pattern pattern = Pattern.compile(ipv4RegExp);
Matcher matcher = pattern.matcher(address);
return matcher.matches();
}
public static boolean isIpv4MulticastAddress(String address) {
Pattern pattern = Pattern.compile(ipv4MulticastRegExp);
Matcher matcher = pattern.matcher(address);
return matcher.matches();
}
}
-bash-3.2$ echo "191.191.191.39" | egrep
'(^|[^0-9])((2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)\.{3}
(2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)($|[^0-9])'
>> 191.191.191.39
(Это DFA, который соответствует всему пространству addr (включая трансляции и т. д.) является ничем иным.
Я думаю, что этот самый короткий.
^(([01]?\d\d?|2[0-4]\d|25[0-5]).){3}([01]?\d\d?|2[0-4]\d|25[0-5])$
Я нашел этот образец очень полезным, кроме того, он позволяет различные обозначения ipv4.
пример кода с использованием python:
def is_valid_ipv4(ip4):
"""Validates IPv4 addresses.
"""
import re
pattern = re.compile(r"""
^
(?:
# Dotted variants:
(?:
# Decimal 1-255 (no leading 0's)
[3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
|
0x0*[0-9a-f]{1,2} # Hexadecimal 0x0 - 0xFF (possible leading 0's)
|
0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's)
)
(?: # Repeat 0-3 times, separated by a dot
\.
(?:
[3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
|
0x0*[0-9a-f]{1,2}
|
0+[1-3]?[0-7]{0,2}
)
){0,3}
|
0x0*[0-9a-f]{1,8} # Hexadecimal notation, 0x0 - 0xffffffff
|
0+[0-3]?[0-7]{0,10} # Octal notation, 0 - 037777777777
|
# Decimal notation, 1-4294967295:
429496729[0-5]|42949672[0-8]\d|4294967[01]\d\d|429496[0-6]\d{3}|
42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|
4[01]\d{8}|[1-3]\d{0,9}|[4-9]\d{0,8}
)
$
""", re.VERBOSE | re.IGNORECASE)
return pattern.match(ip4) <> None
((\.|^)(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0$)){4}
это регулярное выражение не будет принимать 08.8.8.8 или 8.08.8.8 или 8.8.08.8 или 8.8.8.08
находит допустимые IP-адреса, пока IP-адрес обернут вокруг любого символа, кроме цифр (позади или впереди IP-адреса). Создано 4 Backreferences: $+{first}.$+{второй.}$+{третий.}$+{forth}
Find String:
#any valid IP address
(?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
#only valid private IP address RFC1918
(?<IP>(?<![\d])(:?(:?(?<first>10)[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5])))|(:?(?<first>172)[\.](?<second>(:?1[6-9])|(:?2[0-9])|(:?3[0-1])))|(:?(?<first>192)[\.](?<second>168)))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
Notepad++ Replace String Option 1: Replaces the whole IP (NO Change):
$+{IP}
Notepad++ Replace String Option 2: Replaces the whole IP octect by octect (NO Change)
$+{first}.$+{second}.$+{third}.$+{forth}
Notepad++ Replace String Option 3: Replaces the whole IP octect by octect (replace 3rd octect value with 0)
$+{first}.$+{second}.0.$+{forth}
NOTE: The above will match any valid IP including 255.255.255.255 for example and change it to 255.255.0.255 which is wrong and not very useful of course.
замена части каждого octect с фактическим значением, однако вы можете создать свой собственный найти и заменить, который является фактическим полезным для ammend IPs в текстовых файлах:
for example replace the first octect group of the original Find regex above:
(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))
with
(?<first>10)
and
(?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))
with
(?<second>216)
and you are now matching addresses starting with first octect 192 only
Find on notepad++:
(?<IP>(?<![\d])(?<first>10)[\.](?<second>216)[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))
вы все еще можете выполнить замену с помощью групп back-referece точно так же, как до.
вы можете получить представление о том, как выше сопоставлены ниже:
cat ipv4_validation_test.txt
Full Match:
0.0.0.1
12.108.1.34
192.168.1.1
10.249.24.212
10.216.1.212
192.168.1.255
255.255.255.255
0.0.0.0
Partial Match (IP Extraction from line)
30.168.1.0.1
-1.2.3.4
sfds10.216.24.23kgfd
da11.15.112.255adfdsfds
sfds10.216.24.23kgfd
NO Match
1.1.1.01
3...3
127.1.
192.168.1..
192.168.1.256
da11.15.112.2554adfdsfds
da311.15.112.255adfdsfds
используя grep, вы можете увидеть результаты ниже:
From grep:
grep -oP '(?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
0.0.0.1
12.108.1.34
192.168.1.1
10.249.24.212
10.216.1.212
192.168.1.255
255.255.255.255
0.0.0.0
30.168.1.0
1.2.3.4
10.216.24.23
11.15.112.255
10.216.24.23
grep -P '(?<IP>(?<![\d])(?<first>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<second>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
0.0.0.1
12.108.1.34
192.168.1.1
10.249.24.212
10.216.1.212
192.168.1.255
255.255.255.255
0.0.0.0
30.168.1.0.1
-1.2.3.4
sfds10.216.24.23kgfd
da11.15.112.255adfdsfds
sfds10.216.24.23kgfd
#matching ip addresses starting with 10.216
grep -oP '(?<IP>(?<![\d])(?<first>10)[\.](?<second>216)[\.](?<third>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))[\.](?<forth>(:?\d)|(:?[1-9]\d)|(:?1\d{2})|(:?2[0-4]\d)|(:?25[0-5]))(?![\d]))' ipv4_validation_test.txt
10.216.1.212
10.216.24.23
10.216.24.23
^((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]?))$
выше будет регулярное выражение для ip-адреса, как: 221.234.000.112 также для 221.234.0.112, 221.24.03.112, 221.234.0.1
вы можете представить себе все виды адресов, как указано выше
Я бы использовал PCRE и define
ключевые слова:
/^
((?&byte))\.((?&byte))\.((?&byte))\.((?&byte))$
(?(DEFINE)
(?<byte>25[0-5]|2[0-4]\d|[01]?\d\d?))
/gmx
демо:https://regex101.com/r/IB7j48/2
причина этого в том, чтобы избежать повторения (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
рисунок в четыре раза. Другие решения, такие как приведенное ниже, работают хорошо, но они не охватывают каждую группу, как это было бы предложено многими.
/^((\d+?)(\.|$)){4}/
единственный способ иметь 4 группы захвата, чтобы повторить рисунок в четыре раза:
/^(?<one>\d+)\.(?<two>\d+)\.(?<three>\d+)\.(?<four>\d+)$/
захват для IPv4 в Perl, поэтому очень легко
$ echo "Hey this is my IP address 138.131.254.8, bye!" | \
perl -ne 'print "[, , , ]" if \
/\b((?&byte))\.((?&byte))\.((?&byte))\.((?&byte))
(?(DEFINE)
\b(?<byte>25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))
/x'
[138, 131, 254, 8]
самое точное, простое и компактное регулярное выражение IPv4, которое я могу себе представить, это
^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$
но как насчет производительности / эффективности ... Прости, я не знаю, какая разница?
Я думаю, что многие люди, читающие этот пост, будут искать что-то более простое, даже если это позволит некоторым технически недействительным IP-адресам.
это самое простое, что я мог придумать:
Python / Ruby / Perl:
/(\d+(\.|$)){4}/
grep-E (GNU Grep 3.1), awk (версия 20070501) и sed:
/([0-9]+(\.|$)){4}/
марионетка позволила это:
/(\d+[\.$]){4}/
попробуйте это:
\b(([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\.(2[0-5][0-5]|1[0-9][0-9]|[1-9][0-9]|[1-9]))\b
ip address can be from 0.0.0.0 to 255.255.255.255
(((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])[.]){3}((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])$
(0|1)?[0-9][0-9]? - checking value from 0 to 199
2[0-4][0-9]- checking value from 200 to 249
25[0-5]- checking value from 250 to 255
[.] --> represent verify . character
{3} --> will match exactly 3
$ --> end of string
это regex работает для меня:"\<((([1-9]|1[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-9]|1[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))\>"
IPv4-адрес-очень сложная вещь.
Примечание: отступ и подкладка только для целей иллюстрации и не существуют в реальном регулярном выражении.
\b(
((
(2(5[0-5]|[0-4][0-9])|1[0-9]{2}|[1-9]?[0-9])
|
0[Xx]0*[0-9A-Fa-f]{1,2}
|
0+[1-3]?[0-9]{1,2}
)\.){1,3}
(
(2(5[0-5]|[0-4][0-9])|1[0-9]{2}|[1-9]?[0-9])
|
0[Xx]0*[0-9A-Fa-f]{1,2}
|
0+[1-3]?[0-9]{1,2}
)
|
(
[1-3][0-9]{1,9}
|
[1-9][0-9]{,8}
|
(4([0-1][0-9]{8}
|2([0-8][0-9]{7}
|9([0-3][0-9]{6}
|4([0-8][0-9]{5}
|9([0-5][0-9]{4}
|6([0-6][0-9]{3}
|7([0-1][0-9]{2}
|2([0-8][0-9]{1}
|9([0-5]
))))))))))
)
|
0[Xx]0*[0-9A-Fa-f]{1,8}
|
0+[1-3]?[0-7]{,10}
)\b
эти адреса IPv4 обоснованы выше регулярное выражение.
127.0.0.1
2130706433
0x7F000001
017700000001
0x7F.0.0.01 # Mixed hex/dec/oct
000000000017700000001 # Have as many leading zeros as you want
0x0000000000007F000001 # Same as above
127.1
127.0.1
это отверг.
256.0.0.1
192.168.1.099 # 099 is not a valid number
4294967296 # UINT32_MAX + 1
0x100000000
020000000000
String zeroTo255 = "([0-9]|[0-9][0-9]|(0|1)[0-9][0-9]|2[0-4][0-9]|25[0-5])";
it can contain single digit i.e ([0-9]);
It can contain two digits i.e ([0-9][0-9]);
range is (099 to 199)i.e((0|1)[0-9][0-9]);
range is (200 - 249) i.e (2[0-9][0-9]) ;
range is (250-255) i.e(25[0-5]);