Development Tip

정규 표현식으로 IPv4 주소 유효성 검사

yourdevel 2020. 12. 9. 21:52
반응형

정규 표현식으로 IPv4 주소 유효성 검사


IPv4 유효성 검사를 위해 효율적인 정규식을 얻으려고 노력했지만 많은 운이 없었습니다. 언젠가 나는 그것을 가지고 있었던 것처럼 보였지만 (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}이상한 결과를 낳습니다.

$ grep --version
grep (GNU grep) 2.7
$ 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
$ 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
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.255.255
$ 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

나는 이것이 이미 질문하고 대답했는지 확인하기 위해 검색했지만 다른 대답은 단순히 1-3 개의 숫자로 된 4 그룹을 결정하는 방법을 보여 주거나 나를 위해 작동하지 않습니다.


이미 작동하는 대답을 얻었지만 원래 접근 방식에 무엇이 잘못되었는지 궁금한 경우 대답은 번갈아 가며 괄호가 필요하다는 것입니다. 그렇지 않으면 (\.|$)숫자가 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] 범위에 있는지 확인하는 파서를 작성하는 것이 좋습니다. 작동하지 않는 정규식은 이미 읽을 수 없습니다!


새롭고 개선 된 짧은 버전

^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(?!$)|$)){4}$

부정적인 예견 (?!)사용하여 ip가 a로 끝날 수있는 경우를 제거합니다..

이전 답변

^(?:(?: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시작 번호와 a로 끝나는 ip.


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 라이브러리에서 가져온

편집 :이 (\.|$)부분은 이상해 보인다


나는 IPv4 주소와 비슷한 것을 찾고 있었는데, 일반적으로 사용되는 개인 IP 주소의 유효성 검사를 중지 한 정규식 (192.168.xy, 10.xyz, 172.16.xy)이므로이를 달성하기 위해 부정적인 예측을 사용했습니다.

(?!(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 개의 별도 줄에 가독성을 위해 형식을 지정해야합니다.) 정규식 시각화

Debuggex 데모

속도에 최적화되어 있지 않을 수 있지만 '실제'인터넷 주소를 찾을 때만 잘 작동합니다.

실패 할 (그리고해야 할) 것들 :

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

작동 할 (및 작동해야하는) IP :

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 주소'의 유효성을 확인하려는 경우 제공


이것은 일부보다 약간 길지만 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])$

이 게시물을 읽는 많은 사람들은 기술적으로 유효하지 않은 IP 주소와 일치하더라도 더 간단한 정규식을 찾고있을 것이라고 생각합니다. (그리고 다른 곳에서 언급했듯이 정규식은 어쨌든 IP 주소를 올바르게 검증하는 데 적합한 도구가 아닐 수 있습니다.)

제거 ^교체, 해당되는 경우, 그리고 $함께 \b당신이 라인의 시작 / 끝과 일치하지 않으려면.

기본 정규식 (BRE) (GNU grep, GNU sed 및 vim에서 테스트 됨) :

/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/

확장 정규식 (ERE) :

/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/

또는:

/^([0-9]+(\.|$)){4}/

Perl 호환 정규식 (PCRE) (Perl 5.18에서 테스트 됨) :

/^\d+\.\d+\.\d+\.\d+$/

또는:

/^(\d+(\.|$)){4}/

Ruby (Ruby 2.1에서 테스트 됨) :

PCRE로 간주되지만 Ruby는 어떤 이유로 든 Perl 5.18에서 허용하지 않는이 정규식을 허용했습니다.

/^(\d+[\.$]){4}/

이 모든 것에 대한 나의 테스트는 여기에서 온라인 입니다.


'' '이 코드는 저에게 효과적이며 그렇게 간단합니다.

여기에서 ip의 값을 가져 왔고 정규식과 일치 시키려고합니다.

ip="25.255.45.67"    

op=re.match('(\d+).(\d+).(\d+).(\d+)',ip)

if ((int(op.group(1))<=255) and (int(op.group(2))<=255) and int(op.group(3))<=255) and (int(op.group(4))<=255)):

print("valid ip")

else:

print("Not valid")

위의 조건은 값이 모든 4 옥텟에 대해 255를 초과하는지 확인하면 유효하지 않습니다. 그러나 조건을 적용하기 전에 값이 문자열에 있으므로 정수로 변환해야합니다.

group (0)은 일치 된 출력을 인쇄하고 group (1)은 첫 번째 일치 된 값을 인쇄하며 여기서는 "25"등입니다. '' '


다른 모든 답변에서 정규식을 구성했습니다.

(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]))?)$

(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2}))\.){3}(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2})))

텍스트 ( https://regex101.com/r/9CcMEN/2) 에서 일치하는 항목을 찾기위한 테스트

다음은 각 IP 주소 번호에서 유효한 조합을 정의하는 규칙입니다.

  • 한 자리 또는 두 자리 숫자.
  • 로 시작하는 세 자리 숫자 1.

  • 2두 번째 숫자가 0~ 인 경우로 시작하는 3 자리 숫자입니다 4.

  • 25번째 숫자가 0~ 인 경우로 시작 하는 세 자리 숫자입니다 5.

(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2}))\.)네 개의 중첩 된 하위 표현식 세트로 시작해 보겠습니다. 우리는 그것들을 역순으로 살펴볼 것입니다. (\d{1,2})어떤 1 또는 2 자리 숫자 또는 숫자와 일치 0를 통해를 99. (1\d{2})모든 세 자리 숫자로 시작 일치 1( 1두 자리 하였다), 또는 숫자 100스루 199. (2[0-4]\d)숫자와 일치 200를 통해 249. (25[0-5])숫자와 일치 250를 통해 255. 이러한 각 하위 표현식은 |각각 사이에 있는 다른 하위 표현식 내에 둘러싸여 있습니다 (따라서 네 개의 하위 표현식 중 하나가 모두 일치하는 것이 아니라 일치해야 함). 숫자 범위 \.가 일치하게 된 .후 전체 시리즈 (모든 숫자 옵션과\.)는 또 다른 하위 표현식으로 묶여 있으며를 사용하여 세 번 반복됩니다 {3}. 마지막으로 \.마지막 IP 주소 번호와 일치하도록 숫자 범위가 반복됩니다 (이번에는 후행 없음 ). 사이의 값으로 각각의 네 숫자를 제한함으로써 0하고 255,이 패턴은 실제로 유효한 IP 주소와 일치하고 잘못된 주소를 거부 할 수 있습니다.

발췌 : Ben Forta. "정규 표현식 학습."


문자도는 IP 주소의 시작 부분이나 끝 부분에 원하는 경우 ^$메타 문자는 각각 사용되어야한다.

^(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2}))\.){3}(((25[0-5])|(2[0-4]\d)|(1\d{2})|(\d{1,2})))$

텍스트 ( https://regex101.com/r/uAP31A/1) 에서 일치하는 항목을 찾는 테스트


위의 답변은 유효하지만 ip 주소가 줄의 끝이 아니고 텍스트 사이에 있으면 어떻게 될까요.이 정규식은 작동합니다.

암호: '\b((([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]))\b'

입력 텍스트 파일 :

ip address 0.0.0.0 asfasf
 sad sa 255.255.255.255 cvjnzx
zxckjzbxk  999.999.999.999 jshbczxcbx
sjaasbfj 192.168.0.1 asdkjaksb
oyo 123241.24121.1234.3423 yo
yo 0000.0000.0000.0000 y
aw1a.21asd2.21ad.21d2
yo 254.254.254.254 y0
172.24.1.210 asfjas
200.200.200.200
000.000.000.000
007.08.09.210
010.10.30.110

출력 텍스트 :

0.0.0.0
255.255.255.255
192.168.0.1
254.254.254.254
172.24.1.210
200.200.200.200

/^(?:(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(?1)$/m

0에서 255 사이의 숫자에 대해 다음 정규식을 사용합니다.

(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))

위의 정규식은 0에서 255까지의 정수와 일치하지만 256과는 일치하지 않습니다.

따라서 IPv4의 경우 다음 정규식을 사용합니다.

^(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})$

이 구조는 다음과 같습니다. ^(N)((\.(N)){3})$여기서 N은 0에서 255 사이의 숫자를 일치시키는 데 사용되는
정규식입니다 . 이 정규식은 아래와 같이 IP와 일치합니다.

0.0.0.0
192.168.1.2

그러나 아래는 아닙니다.

10.1.0.256
1.2.3.
127.0.1-2.3

IPv4 CIDR (Classless Inter-Domain Routing)의 경우 다음 정규식을 사용합니다.

^(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))$

구조는 다음과 같습니다. ^(N)((\.(N)){3})\/M$여기서 N은 0에서 255 사이의 숫자를 일치시키는 데 사용되는 정규식이고 M은 0에서 32 사이의 숫자를 일치시키는 데 사용되는
정규식입니다 . 이 정규식은 아래와 같이 CIDR과 일치합니다.

0.0.0.0/0
192.168.1.2/32

그러나 아래는 아닙니다.

10.1.0.256/16
1.2.3./24
127.0.0.1/33

"10.0.0.0/16", "192.168.1.1/32"이 정규식을 사용하는 것과 같은 IPv4 CIDR 목록은 다음과 같습니다 .

^("(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))")((,([ ]*)("(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))"))*)$

이는 다음 구조에 있습니다. ^(“C”)((,([ ]*)(“C”))*)$여기서 C는 CIDR (예 : 0.0.0.0/0)을 일치시키는 데 사용되는 정규식입니다.
이 정규식은 아래와 같이 CIDR 목록과 일치합니다.

“10.0.0.0/16”,”192.168.1.2/32”, “1.2.3.4/32”

그러나 아래는 아닙니다.

“10.0.0.0/16” 192.168.1.2/32 “1.2.3.4/32”

짧아 질지 모르지만 나에게는 그렇게 잘 이해하기 쉽습니다.

도움이 되었기를 바랍니다.


    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와 같은 일부 OS에는 약간의 문제가 있습니다. 이 정규식은 192.168.100.009와 같은 ipv4 주소를 허용합니다. 여기서 Linux의 009는 8 진수 값으로 간주되므로 주소가 생각한 주소가 아닙니다. 정규식을 다음과 같이 변경했습니다.

    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";

이제 정규 표현식을 사용하면 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입니다.


이게 가장 짧은 것 같아요.

^(([01]?\d\d?|2[0-4]\d|25[0-5]).){3}([01]?\d\d?|2[0-4]\d|25[0-5])$

이 샘플은 매우 유용하며 또한 다른 ipv4 표기법을 허용합니다.

파이썬을 사용한 샘플 코드 :

    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 개의 역 참조 생성 : $ + {first}. $ + {second}. $ + {third}. $ + {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.

각 옥 텍트의 일부를 실제 값으로 대체하지만 텍스트 파일에서 IP를 수정하는 데 실제로 유용한 고유 한 찾기 및 바꾸기를 빌드 할 수 있습니다.

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

이전과 똑같은 방식으로 역 참조 그룹을 사용하여 교체를 수행 할 수 있습니다.

위의 내용이 아래에서 어떻게 일치하는지 알 수 있습니다.

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

IPv4 주소는 매우 복잡한 것입니다.

참고 : 들여 쓰기와 안감은 설명을위한 것이며 실제 RegEx에는 존재하지 않습니다.

\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 주소는 위의 RegEx에 의해 확인됩니다.

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

^((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]?))$


위는 221.234.000.112와 같은 ip 주소에 대한 정규식입니다. 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 개의 캡처 그룹을 갖는 유일한 다른 방법은 패턴을 4 번 반복하는 것입니다.

/^(?<one>\d+)\.(?<two>\d+)\.(?<three>\d+)\.(?<four>\d+)$/

따라서 perl에서 ipv4를 캡처하는 것은 매우 쉽습니다.

$ echo "Hey this is my IP address 138.131.254.8, bye!" | \
  perl -ne 'print "[$1, $2, $3, $4]" 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)$

하지만 성능 / 효율성은 어떨까요? 죄송합니다. 누가 신경 쓰나요?


이 시도:

\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

다음은 IP 주소의 유효성을 검사하는 정규식 표현식입니다.

^((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]?)$

쉬운 방법

((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]{0,1})\.){3}(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]{0,1})

데모


이것은 유효한 IP (앞에 0이 추가되지 않음) 만 일치하지만 '기능'[예 : 예약, 개인 등]에 관계없이 0-255의 옥텟과 일치하며 앞뒤에 공백이있을 수있는 인라인 일치를 허용합니다. IP 뒤 또는 CIDR 표기법을 사용할 때.

grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)'

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.2'
10.0.1.2

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2'
ip address 10.0.1.2

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2 255.255.255.255'
ip address 10.0.1.2 255.255.255.255

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2/32'
ip address 10.0.1.2/32

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2.32'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address10.0.1.2'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.256'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '0.0.0.0'
0.0.0.0

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.255'
255.255.255.255

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.256'
$

물론 IP가 인라인 인 경우에는 전체 IP 만 원하고 IP 만 원하면 grep 옵션 "-o"와 선호하는 공백 트리머를 사용할 수 있습니다.

파이썬을 사용하는 사람들에게는 대략 다음과 같습니다.

>>> ipv4_regex = re.compile(r'(^| )((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])($| |/)')
>>> ipv4_regex.search('ip address 10.1.2.3/32')
<re.Match object; span=(10, 20), match=' 10.1.2.3/'>

If you're picky (lazy) like me, you probably would prefer to use grouping to get the whole IP and nothing but the IP, or the CIDR and nothing but the CIDR or some combination thereof. We can use (?P) syntax to name our groups for easier reference.

>>> ipv4_regex = re.compile(r'(?:^| )(?P<address>((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]))(?P<slash>/)?(?(slash)(?P<cidr>[0-9]|[12][0-9]|3[0-2]))(?:$| )')
>>> match = ipv4_regex.search('ip address 10.0.1.2/32')
>>> match.group('address')
'10.0.1.2'
>>> match.group('cidr')
'32'
>>> "".join((match.group('address'), match.group('slash'), match.group('cidr')))
'10.0.1.2/32'

There's ways of not using just regex, of course. Here's some conditions that you could check (this one doesn't find inline, just validates the passed address is valid).

First check is that each char in the address is a digit or a '.'

Next checking that there are exactly 3 '.'

The next two checks check that each octet is between 0 and 255.

And the last check is that no octets are prepended with a '0'

def validate_ipv4_address(address):
    return all(re.match('\.|\d', c) for c in address) \
        and address.count('.') == 3 \
        and all(0 <= int(octet) <= 255 for octet in address.split('.')) \
        and all((len(bin(int(octet))) <= 10 for octet in address.split('.'))) \
        and all(len(octet) == 1 or d[0] != '0' for octet in address.split('.'))


>>> validate_ipv4_address('255.255.255.255')
True
>>> validate_ipv4_address('10.0.0.1')
True
>>> validate_ipv4_address('01.01.01.01')
False
>>> validate_ipv4_address('123.456.789.0')
False
>>> validate_ipv4_address('0.0.0.0')
True
>>> validate_ipv4_address('-1.0.0.0')
False
>>> validate_ipv4_address('1.1.1.')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''
>>> validate_ipv4_address('.1.1.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''
>>> validate_ipv4_address('1..1.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''

(bitwise, each octet should be 8 bits or less, but each is prepended with '0b')

>>> bin(0)
'0b0'
>>> len(bin(0))
3
>>> bin(255)
'0b11111111'
>>> len(bin(256))
11

참고 URL : https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp

반응형