0

I coded an app with tkinter. Now I want to add conditions/pattern in a entry box when the user use it. I want to force the user to use these pattern:

The entry must begin by this pattern `^#\d+\s[A-I]\d+(,|;|-|)`
if there is a `,` or `-` in the string, the pattern must be the same plus `[A-I]\d+`
If there is `;` in the string, redo the first pattern
if after  `^#\d+\s[A-I]\d+(,|;|-|)` there is nothing, do nothing
I used regex conditions but nothing happened. 
I use this `^#\d+\s[A-I]\d+(,|;|-|)(?:(?=,)[A-I]\d+)`

I use this program to check my regex expression

user = input("Please enter user : ")
while not re.match(r"#\d+\s[A-Z]\d+(?:[,-][A-Z]\d+)*(?:;#\d+\s[A-Z]\d+(?:[,-][A-Z]\d+)*)*", user):
    print ("Error! ")
    user = input("user : ")
print("user "+ user)
Béa
  • 101
  • 2
  • 9
  • I highly recommend reading something like https://docs.python.org/3/library/re.html and implementing yourself, so you can change what you want if needed. The rules are also not entirely clear: for example according to the rules there can not be a , or a ;, but there are rules for the characters behind these. – DwightFromTheOffice Jun 21 '21 at 09:03
  • If you don't want to use regular expressions, use [string methods](https://docs.python.org/3/library/stdtypes.html#string-methods). You can split the string value into characters and analyze what is in what position. `value = "#2-A;#,d1"` -> list(value) -> `['#', '2', '-', 'A', ';', '#', ',', 'd', '1']`. This, of course, requires writing a lot of if-else blocks. – 8349697 Jun 21 '21 at 10:25
  • See also: https://stackoverflow.com/questions/3478890/how-to-insert-only-some-specified-characters-in-a-tkinter-entry-widget, https://stackoverflow.com/questions/4140437/interactively-validating-entry-widget-content-in-tkinter, https://stackoverflow.com/questions/43360921/dont-understand-tkinter-entry-box-validatiom – 8349697 Jun 21 '21 at 10:26
  • Thank you for your answers but I already read these links and documentation. The pattern is something like #number A4-B7;#number A1,B9 or #number A1 or #number C7 or #number E78-F39 or #number E74;#number Q7 – Béa Jun 21 '21 at 11:49
  • If you don't know where to start, try using a tool like this: https://pythex.org Start with the simplest special characters and sequences. `\d+` is a sequence of digits, `[A-Z]` is an uppercase letter. Practice writing regular expressions for each of your patterns separately. For example, `^#\d+ [A-Z]\d{1}$` would match `#10345 A1` or `#2379 C7`. – 8349697 Jun 21 '21 at 13:24
  • Ok but how to merge all regex pattern? I have to use if conditions for each pattern, if this can not be possible? But I can't do this because the length of the entry can be variable. I can have #number A1, B9, C7;#number A89-Z78;#number A89-Z78 – Béa Jun 21 '21 at 13:41
  • 1
    Well, you can write a regex for each pattern and then check if the string matches any of the patterns (with for loop and if conditions). But the point is, as you practice writing regular expressions, you will see which parts of your patterns are similar. And in the parts where they differ, you can use the `|` operator (or). You can also use groups, for example `(-|,)` - hyphen or comma. Etc. The documentation describes all the [syntax](https://docs.python.org/3.9/library/re.html#regular-expression-syntax). – 8349697 Jun 21 '21 at 14:42
  • If the user can enter multiple values separated by semicolons, make a list of values from this string. Check each value separately, otherwise it will be a terrible regex. – 8349697 Jun 21 '21 at 15:24
  • 1
    My advice is to start by solving the problem for a single rule. Learn how to use regular expressions to match a string against a pattern. Once you can do it for the simplest of patterns, it becomes much easier to extend the pattern. Don't try to solve the entire problem at once. – Bryan Oakley Jun 21 '21 at 15:39
  • Ok thank you for your answers. I will try to learn it ! – Béa Jun 22 '21 at 06:20
  • @BryanOakley, 8349697 See edits pls – Béa Jun 22 '21 at 10:20

1 Answers1

1

Note that [A-I] does not match the Q in Q7. You can use [A-Z] to extend the range and use a repeating group for the first and the second pattern.

You might use

#\d+\s[A-Z]\d+(?:[,-][A-Z]\d+)*(?:;#\d+\s[A-Z]\d+(?:[,-][A-Z]\d+)*)*

The pattern matches:

  • #\d+\s[A-Z]\d+ Match # 1+ digits, a whitespace char and 1+ digits
  • (?:[,-][A-Z]\d+)* Optionally repeat matching , or - char A-Z and 1+ digits
  • (?: Non capture group
    • ;#\d+\s[A-Z]\d+ Match ; and the first pattern
    • (?:[,-][A-Z]\d+)* Optionally repeat matching the second pattern
  • )* Close non capture group and optionally repeat the whole part

Regex demo

Or if you want to allow spaces as well:

#\d+\s[A-Z]\d+(?:[,-]\s?[A-Z]\d+)*(?:;#\d+\s[A-Z]\d+(?:[,-]\s?[A-Z]\d+)*)*

Regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • Thank you so much. But I have a question: Why I can put a space after and before a , ? It is because * ? I don't want to allow a space. (example A1, A2 ) I want something like that A1,A2. And after ; I want to allow only #\d+\s[A-Z]\d+. But here I don't understand why I can put whatever I want – Béa Jun 23 '21 at 06:40
  • @Béa if you don't want to match a space before or after the comma, you can use the first pattern (which you already did in the updated question). If you enter anything you want, your code will return `Error!` so that looks ok right? Can you update this link with what you want and do not want to match, and share it back in the comments? https://regex101.com/r/I5Twn5/1 – The fourth bird Jun 23 '21 at 08:18
  • Sorry the regex expression works but when I use it through python and tkinter it doesn't work. But it is an another porblem. I will post a new post. – Béa Jun 23 '21 at 10:06