25

I've written a regular expression that matches any number of letters with any number of single spaces between the letters. I would like that regular expression to also enforce a minimum and maximum number of characters, but I'm not sure how to do that (or if it's possible).

My regular expression is:

[A-Za-z](\s?[A-Za-z])+

I realized it was only matching two sets of letters surrounding a single space, so I modified it slightly to fix that. The original question is still the same though.

Is there a way to enforce a minimum of three characters and a maximum of 30?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
CorayThan
  • 15,119
  • 26
  • 101
  • 148
  • Any number of letters w/ any number of single spaces, with min 3 and max 30 characters? It sounds like `[A-Za-z ]{3,30}` will do the job, since it fits description. – nhahtdh Mar 08 '13 at 11:17
  • @nhahtdh That would allow multiple spaces in the row. It seems there is no graceful solution. – CorayThan Mar 08 '13 at 19:00
  • It is possible, if you state **all** the requirements. I can only see your requirement of multiple spaces in a row from your regex, not from your description. – nhahtdh Mar 08 '13 at 19:03
  • "with any number of single spaces between the letters." That was meant to mean there can be any number of spaces, so long as they are "single spaces," i.e. not more than one space in a row. I tried to be explicit about that requirement, but I guess it was difficult to describe. – CorayThan Mar 09 '13 at 08:23
  • This looks like a canonical question, but it is fairly late (2013), 5 years in. – Peter Mortensen Jul 31 '19 at 16:05
  • A more general "question" is *[Reference - What does this regex mean?](https://stackoverflow.com/questions/22937618)*. It has *"Min/max ranges (all inclusive)"*. – Peter Mortensen Jul 31 '19 at 16:10

4 Answers4

41

Yes

Just like + means one or more you can use {3,30} to match between 3 and 30

For example [a-z]{3,30} matches between 3 and 30 lowercase alphabet letters

From the documentation of the Pattern class

X{n,m}    X, at least n but not more than m times

In your case, matching 3-30 letters followed by spaces could be accomplished with:

([a-zA-Z]\s){3,30}

If you require trailing whitespace, if you don't you can use: (2-29 times letter+space, then letter)

([a-zA-Z]\s){2,29}[a-zA-Z]

If you'd like whitespaces to count as characters you need to divide that number by 2 to get

([a-zA-Z]\s){1,14}[a-zA-Z]

You can add \s? to that last one if the trailing whitespace is optional. These were all tested on RegexPlanet

If you'd like the entire string altogether to be between 3 and 30 characters you can use lookaheads adding (?=^.{3,30}$) at the beginning of the RegExp and removing the other size limitations

All that said, in all honestly I'd probably just test the String's .length property. It's more readable.

candlejack
  • 1,143
  • 2
  • 20
  • 48
Benjamin Gruenbaum
  • 246,787
  • 79
  • 474
  • 476
  • @zvzdhk I don't understand your question, would you like examples of how the {n,m} quantifier should be used? – Benjamin Gruenbaum Mar 08 '13 at 07:10
  • 1
    Yes, [a-z]{3,30} matches 3 to 30 letters, but mine would match 3 to 30 sets of two letters maybe with a space in between them, rather than real letters. Or at least that's what playing around with [regexpal](http://regexpal.com/) seems to indicate to me. – CorayThan Mar 08 '13 at 07:12
  • @zvzdhk Fair enough :) I just edited, CorayThan please see my edit. – Benjamin Gruenbaum Mar 08 '13 at 07:13
  • Your code snippet doesn't work. If I got OP's issue correctly, `aaaaaa bbbbbbb` should pass too. But it does not. – bsiamionau Mar 08 '13 at 07:16
  • @zvzdhk In that case all he needs to do is change `[a-zA-Z]` to `[a-zA-Z]+\s` . Thank you for helping me improve my answer by the way. – Benjamin Gruenbaum Mar 08 '13 at 07:16
  • Same goes for your last solution. It works except that the white spaces don't count for a space! So if there are, say, 3 white spaces you can have the java equivalent of a 33 length string. – CorayThan Mar 08 '13 at 07:28
  • @CorayThan I did not understand you wanted whitespaces not to count, I'm editing my answer, it only involves dividing the number of repeats by 2 :) – Benjamin Gruenbaum Mar 08 '13 at 07:31
  • Haha, that would totally work ... if not for the fact that the \s needs to be \s?. I don't want to require the space between characters. When you add the ? it means you can create a match with only 15 characters with your solution. Essentially this is to make people chose "realistic" names for their characters. So I'm fine with someone being "Bob of booger Square" but not "bo b x" (image extra spaces, SO removed them) because it would make it very difficult for other players to search for their name with extra spaces. – CorayThan Mar 08 '13 at 07:38
  • Honestly, for your own sake, if the length check applies to the entire string I'd just check the string's .length property. It's easier and faster. – Benjamin Gruenbaum Mar 08 '13 at 07:41
  • Yes, that's probably true. – CorayThan Mar 08 '13 at 07:44
  • i want any characters or any thing but length must be 8. how to achieve? – Irfan Nasim Apr 03 '17 at 06:12
7

This is what you are looking for

^[a-zA-Z](\s?[a-zA-Z]){2,29}$

^ is the start of string

$ is the end of string

(\s?[a-zA-Z]){2,29} would match (\s?[a-zA-Z]) 2 to 29 times..

Anirudha
  • 30,881
  • 7
  • 64
  • 81
  • This is much closer. I actually do want \s? rather than \s* because I want a maximum of one space. The only problem is I wanted spaces to be included in the character count. I was just thinking it would be fun to incorporate in my regex the equivalent of "(myString.length() > 2 && myString.length() < 31)", so I don't need extra checks in java. – CorayThan Mar 08 '13 at 07:22
  • Also, what is the practical purpose of ^ and $? At least in java my matcher seems to work without those. – CorayThan Mar 08 '13 at 07:26
  • @CorayThan if you use the above regex without ^,$ with **find** method,it would match anywhere..so it would also match any input that has more than 30 characters..if you use **matches** method it would match the pattern exactly and so you don't need to use ^,$ if you use matches method..more info [here](http://stackoverflow.com/questions/4450045/difference-between-matches-and-find-in-java-regex) – Anirudha Mar 08 '13 at 07:30
  • @CorayThan i guess this has solved your problem..if so you can accept the ans or atleast upvote for my efforts..right! – Anirudha Mar 08 '13 at 07:34
  • I suspect the real answer to my issue is that it's impossible. Like I said, counting white space the string length can exceed 30 with your answer. – CorayThan Mar 08 '13 at 07:42
  • @CorayThan It's possible, it can be proven (formally) that the intersection of two regular languages is also regular. Formally, I can _prove_ that there _exists_ a RegExp that matches your case (being exactly 30 chars and containing letters followed by whitespaces). I just don't think that you should use it :) (probably answer is using (?=expr) to check length without consuming and then consume with the current solution. – Benjamin Gruenbaum Mar 08 '13 at 07:46
  • Good point. For sure, it is possible. But not possible with a reasonable regex. :) – CorayThan Mar 08 '13 at 07:49
  • @CorayThan you can do it separately..y do you want to do it with regex alone..isn't that **overkill** – Anirudha Mar 08 '13 at 08:14
4

Actually Benjamin's answer will lead to the complete solution to the OP's question. Using lookaheads it is possible to restrict the total number of characters AND restrict the match to a set combination of letters and (optional) single spaces.

The regex that solves the entire problem would become

(?=^.{3,30}$)^([A-Za-z][\s]?)+$

This will match AAA, A A and also fail to match AA A since there are two consecutive spaces. I tested this at http://regexpal.com/ and it does the trick.

Community
  • 1
  • 1
mvreijn
  • 2,462
  • 23
  • 37
0

you should use

[a-zA-Z ]{20}

[for allowed characters]{for limit of number of characters}

Naitik
  • 960
  • 11
  • 31