2

I am trying to get my head around the regex module in python. I tried to get my program to match the following pattern from a line of text that the user inputs:

a number between 8-13 "/" a number between 0-15

For example: 8/2, 11/13, 10/9, etc.

The pattern that I came up with was:

upstream = re.compile(r'[8-9|1[0-3][/][0-9|1[0-5]')

However, this regex works with mixed results:

Enter a slot/port : 8/2    
['8/2']                    # This is correct

Enter a slot/port : 1/0    
['1/0']                    # This should print the "else" statement

Enter a slot/port : 8/15
['8/1']                    # The output is incomplete

The problem seems to stem from the forward slash, but I am not sure. I do know that I need some assistance in solving this issue. If anyone can help me solve this, I would greatly appreciate it.

The complete script is below.

import re
pattern = re.compile(r'[8-9|1[0-3][/][0-9|1[0-5]')

upstream = input("Enter a slot/port : ")

if re.search((pattern), upstream):
    print(re.findall(pattern, upstream))
else:
    print("We have a problem")

Thanks in advance :)

6
  • 1
    Check out this website which helps test regex patterns for python. Commented Jul 19, 2021 at 22:39
  • 1
    You need (?<!\d)(?:[89]|1[0-3])/(?:[0-9]|1[0-5])(?!\d) Commented Jul 19, 2021 at 22:39
  • Thanks, Wiktor! That works. Now I just have to continue reading the documentation to fully understand what is going on with the ? and !. :) Commented Jul 19, 2021 at 23:12
  • If you think a '/' might interfere with user input, it would also be reasonable to add two input() calls, one for the slot, and then one for the port. Remembering to include a / is probably not as important to you as the two numbers. Commented Jul 20, 2021 at 2:32
  • 2
    Do you have to use regex? It's trivially easy to do this using str.split() and then parsing the resulting strings into integers. Commented Jul 20, 2021 at 21:08

2 Answers 2

1

Your expression is not well-formed, as you utilized square brackets where round brackets must be. [8-9|1[0-3] and [0-9|1[0-5] both are bad patterns as [8-9 and [0-9 are not closed character classes.

Use

\b(?:[89]|1[0-3])/(?:[0-9]|1[0-5])\b

See regex proof.

EXPLANATION

--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  (?:                      group, but do not capture:
--------------------------------------------------------------------------------
    [89]                     any character of: '8', '9'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    1                        '1'
--------------------------------------------------------------------------------
    [0-3]                    any character of: '0' to '3'
--------------------------------------------------------------------------------
  )                        end of grouping
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  (?:                      group, but do not capture:
--------------------------------------------------------------------------------
    [0-9]                    any character of: '0' to '9'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    1                        '1'
--------------------------------------------------------------------------------
    [0-5]                    any character of: '0' to '5'
--------------------------------------------------------------------------------
  )                        end of grouping
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for this great great response! Sorry that I took so long to answer, I wasn't aware that the question was reopened. Using the boundary really made a huge difference, since I wanted to ensure that useless input such as c8/9 would be ignored. I have marked your response as the answer.
1

The regex you are using requires 1's on both sides of the "/", use the "|" symbol to imply OR statements such that there is a choice of "a or "b", "a|b". This would give you a regex more in line with "[8-9]|1[0-3]" for before the "/" and "[0-9]|1[0-5]" after. So in total, when using "(regex)" to group parts you want to be expressed separately, you could end up with a regex more inline with "([8-9]|1[0-3])/([0-9]|1[0-5])".

Hope this was helpful!

1 Comment

Yes, it helped me a lot, thanks for responding. My problem was not understanding how to properly group the different subpatterns in order to get the desired result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.