#๐Ÿ”’ Regex help

235 messages ยท Page 1 of 1 (latest)

steel pollen
#

Im not sure how to get 255 accepted


import re
import sys


def main():
    print(validate(input("IPv4 Address: ")))

def validate(ip):
    return re.search(r'[0-2][0-5][0-5]\.[0-2][0-5][0-5]\.[0-2][0-5][0-5]\.[0-2][0-5][0-5]', ip)



if __name__ == "__main__":
    main()
proper quartzBOT
#

@steel pollen

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

steel pollen
#

im new to regex

robust rampart
#

It looks like your regex will accept 255 fine (unless I missed a typo or something). What it won't accept are two-digit numbers, which is why it won't accept 10 (it would accept 010 though). It also won't accept numbers where the second or third digit are greater than 5 (so no 199 and 246). You can fix all that by spelling out all the possible forms of numbers between 0 and 255, but honestly I think it will be easier to just validate that you have four sequences of 1-3 digits separated by dots and then split on . and convert to int to validate that the numbers are in range.

topaz cove
#

What if i type 1.2.3.4

steel pollen
#

should i use groups?

#

then convert to ints

steel pollen
robust rampart
#

On another note, it seems weird that your function is called validate, but what it seems to be doing is to search for an IP in the given string.

steel pollen
topaz cove
steel pollen
robust rampart
#

But search doesn't return true or false. It returns a match or None. And to return a match, the given string only needs to contain a match. It doesn't have to match the regex in its entirety.

steel pollen
robust rampart
#

For example, if you input "This text contains the IP 255.255.255.255 haha", then your current code will output "255.255.255.255".

steel pollen
#

should i use matchfull?

robust rampart
#

If that's not what you want, you want to us fullmatch, not search.

#

Yes, exactly.

steel pollen
#

ok sure

#

now i keep getting none

#
import re
import sys


def main():
    print(validate(input("IPv4 Address: ")))

def validate(ip):
    return re.fullmatch(r'[0-2][0-5][0-5]\.[0-2][0-5][0-5]\.[0-2][0-5][0-5]\.[0-2][0-5][0-5]$', ip)



if __name__ == "__main__":
    main()
#

any advice?

robust rampart
#

As I said, your current regex will not match any numbers with less than three digits (also any number with the digits six through 9 in them).

jagged turtle
#

Right now you're matching for range 0-2 exactly one time

#

Either change to [0-255] or use [0-2]?[0-5]?[0-5]?

#

-# Its been a bit since ive used builtin re

steel pollen
#

i want to take numbers 0-255

jagged turtle
#

noted, try the other option

robust rampart
#

[0-255] is another way to write [0125]. That will not do what you want.

jagged turtle
#

Regex101 is your best friend

broken jacinth
steel pollen
robust rampart
#

Note that [0-2]?[0-5]?[0-5]? will match the empty string (and will still not match 199). I still stand by my earlier suggestion to work with ints instead of regexes to validate the range.

steel pollen
#

hmm ok

#

should I split it then

jagged turtle
#

This also wont catch all ips

#

Split it and do numeric comparison on each int

#

192.168.0.1 is a valid NAT IP and would fail that regex even if it was working

robust rampart
#

On an unrelated note, be aware that some tools and APIs interpret leading 0s as indicating octal numbers, so you might not want to allow leading 0s in the IP depending on what you want to do with it.

steel pollen
jagged turtle
#

You should be able to search online for common IP regex algorithms if you're confused

steel pollen
jagged turtle
#

Use something called Regex 101

#

https://regex101.com/

Try out regex here and it has an explaination tab on the side. It also comes with a quick reference guide

regex101

Regular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java, C#/.NET, Rust.

steel pollen
#

Thanks!

jagged turtle
#

All you gotta do is make sure you have the python flavour selected otherwise the regex may be slightly different

golden jasper
#

You code just described
I need 0-2 for first number, 0-5 for second number and 0-5 for the third number

steel pollen
golden jasper
#

With dot separation etc.

steel pollen
north sphinx
#
if validate(f"{i}.1.1.1") == False:
            assert validate(f"{i}.1.1.1") == False

what?

jagged turtle
#

that will check for each number in "2" "5" "5". (using for on a string iters the chars)

steel pollen
#

i want to check between 0-255

#

so should i use range?

jagged turtle
#

Yeah

steel pollen
#

i havent done it in a while lol

jagged turtle
#

for i in range(1, 256, 1)
1 - Start point (Inclusive)
256 - End point (EXCLUSIVE!)
1 - Step (not really needed since that's default anyway)

golden jasper
#

You would need more than 1 options with or in regex

keen cedar
#

what about {1,3} in regex?

#

oh wait that wouldn't work, nm

jagged turtle
#

Number of last token to match XD

steel pollen
#

re.fullmatch(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$', ip)
#

its this from online

#

stack overflow

jagged turtle
#

Yeah thats a method :D

steel pollen
#

lol yea

#

how to do this?

#

done this ```py
for i in range(255):
assert validate(f"{i}.1.1.1") == True

jagged turtle
#

Should be for i in range(1, 256, 1) (see my above message for why)

north sphinx
#

and four of them (nested)

steel pollen
#

thanks

#

tests arnt testing lol

north sphinx
#
for i in range(1, 256):
  for j in range(1, 256):
    for k in range(1, 256):
      for l in range(1, 256):
        assert validate(f"{i}.{j}.{k}.{l}") == True
steel pollen
north sphinx
#

you want to vary each byte from 1-255

steel pollen
#

saves time

north sphinx
steel pollen
#
test_numb3rs.py catches numb3rs.py only checking if first byte of IPv4 address is in range
    expected exit code 1, not 0```
steel pollen
jagged turtle
#

I assume you're doing this for like learning and stuff

steel pollen
#

yea

#

its an online course

jagged turtle
#

Just checking since the ipaddress module does exist-

steel pollen
#

im on week 7/9

north sphinx
steel pollen
jagged turtle
#

That has to loop 4.2 billion ips.

#

Its slow.

north sphinx
#

yeh it would be

jagged turtle
#

Vector math would like to speak with you

#

or yknow...

steel pollen
#

lets stick to the topic

#

both methods dont work for my checks

north sphinx
#

okay anywhere where the rules are clearly laid out?

steel pollen
#

yea

#

check this

jagged turtle
#

We just got XY problemed.

steel pollen
jagged turtle
#

The XY problem is You came up with a solution (Y) for problem X, but it wasnt working so you asked how to fix solution Y

#
byte_data = ip.split()

for byte in byte_data:
    if 0<int(byte)<256:
         ... # Other logic

You check 4 times and its a guaranteed validity.

north sphinx
#

*split(".")

jagged turtle
#

Good catch

#

Im too used to my custom string methods

#

They auto grab the sep

steel pollen
north sphinx
#

probably add a try/except for the non-numerical invalid test cases

#

!d str.isdecimal or this

proper quartzBOT
#

str.isdecimal()```
Return `True` if all characters in the string are decimal characters and there is at least one character, `False` otherwise. Decimal characters are those that can be used to form numbers in base 10, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in the Unicode General Category โ€œNdโ€.
north sphinx
#

but that might trip you up because it includes 0-9 from other scripts

#

so try/except it is

jagged turtle
#

Wayyy too used to seeing .isdigit()

steel pollen
#

im doing this in pytest btw

#

how abouts to do it

#

i need to hardcode a value

jagged turtle
#

Damn

north sphinx
#

!d str.isdigit

proper quartzBOT
#

str.isdigit()```
Return `True` if all characters in the string are digits and there is at least one character, `False` otherwise. Digits include decimal characters and digits that need special handling, such as the compatibility superscript digits. This covers digits which cannot be used to form numbers in base 10, like the Kharosthi numbers. Formally, a digit is a character that has the property value Numeric\_Type=Digit or Numeric\_Type=Decimal.
jagged turtle
#

Im stupid

#

Good to know that that's somehow worse XDDD

north sphinx
jagged turtle
#

Also nice to see someone taking the free CS50

#

-# Ive been contemplating

steel pollen
#

i need to do more projects after i finish tho

jagged turtle
#

Fair fair, if you need inspo, dm me, I always have reasonable ish project ideas

steel pollen
#

i dont have access to a terminal like bloomberg tho

#

i wish i did ๐Ÿ˜ฆ

jagged turtle
#

XD Fair

#

Uhhh finance projects...

#

Denominations counters
Conversion Calculators
Stock readers (if you cover that sector)

steel pollen
#

ive done a bitcoin indexer using an api

jagged turtle
#

Like GBP to USD or USD to AUD, fetching the latest data ofc

steel pollen
#

oh ok

#

nice

#

ill try

jagged turtle
#

Also ive personally never used pytest, I usually define my own testing methods

steel pollen
#

im still failing the tests

jagged turtle
#

Then again im insane apparently as far as devs go XD

#

Hmm the module does explicitly say about regex...

steel pollen
#

true

#

maybe i should implement a regex that checks the first byte

#

using group(1)

jagged turtle
#

Im experimenting with the builtin re module instead of the installable one

steel pollen
#

ok i didnt install anything either

jagged turtle
#

Do you have access to the tests they use for PyTest?

steel pollen
#

no i have to make it robust myself

#

which is annoying

jagged turtle
#

Sigh, if you had access to the tests ๐Ÿ˜ญ

steel pollen
#

should i just submit

#

its just one check

#

im pretty sure i dont need to get all ticks for the cert

jagged turtle
#

Thats how prod apis die

steel pollen
jagged turtle
#

"Its just one check"

steel pollen
#

loll

jagged turtle
#

Ive seen too many apps die from just one check

#

I think I have a hit

steel pollen
#

what is it

jagged turtle
#

Im just running a full Ip range test

steel pollen
#

ok lmk how it is

jagged turtle
#

Could be a while, im remoted onto my dev laptop

steel pollen
#

ill come back in 10 mins lol

ashen creek
#

|

steel pollen
#

?

jagged turtle
#

Ok just dropped python all my threads and 24 worker processes

#

Still going to take a bit, but nowhere near as long

#

Golden.

#
ip_expr = re.compile(
    r"\b("
    r"(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])"
    r"\."
    r"(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])"
    r"\."
    r"(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])"
    r"\."
    r"(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])"
    r")\b"
)

This is the regex im using

steel pollen
#

cant u use {4}

#

instead of repeating the line 4 times

jagged turtle
#

Could allow for an ending .

#

Besides the fact that windows is screaming for resources right now, its working

steel pollen
#

man

#

this is so inefficent

jagged turtle
#

Im afraid IPs are kinda like that

#

Thats why we have the ipaddress module

steel pollen
#

shouldnt we just check for the first byte

#

like it says in the test check

#

although urs is correct in the long run

north sphinx
#

it's saying your test only checks for the first byte

jagged turtle
#

Well no because what if its:
"192.269.0.15"

twilit drum
#

Are you testing... every IP address? Isn't that a little ridiculous?

jagged turtle
#

we make sure it workin

north sphinx
steel pollen
#

i dont want to test for all ips tbh

#

too long

north sphinx
#

honestly I'm confused on what the failing test is expecting

north sphinx
jagged turtle
#

Eh true, .join is a thing

#

removes readability a lil but :P

#

Also me literally done.

north sphinx
#

anything outside sys/re is disallowed

#

so, ๐Ÿคท

jagged turtle
#

Damn no builtin ipaddress i guess

steel pollen
#

idk

#

so what now?

jagged turtle
#

Say screw it and utilise split. See what you can roll around with that

steel pollen
#

i need to hardcode values tho

jagged turtle
#

ips = [
    "127.0.0.1",
    "255.255.255.255",
    "512.512.512.512",
    "1.2.3.1000",
    "192.168.001.1",
    "cat"
]

Like that you mean?

#

For loop through the values and work out what checks you need to pass

steel pollen
#

yep like that is good

#

then i can check if its num,

jagged turtle
#

I will say, I do have a working implementation

steel pollen
#

def test_first():
assert validate("256.1.1.1") == False
assert validate("1.256.1.1") == False
assert validate("1.1.256.1") == False
assert validate("1.1.1.256") == False

proper quartzBOT
#

Hey @steel pollen!

Please edit your message to use a code block

```py
print('Hello, world!')
```

This will result in the following:

print('Hello, world!')```
steel pollen
#

i just done this

#

and it works lol

#

although could be done better

#

!close

proper quartzBOT
#
Python help channel closed with !close

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.