3

I have regex as follows:

     /^(\d|-|\(|\)|\+|\s){12,}$/

This will allow digits, (, ), space. But I want to ensure string contains atleast 8 digits. Some allowed strings are as follows:

      (1323  ++24)233
      24243434 43
      ++++43435++4554345  434

It should not allow strings like:

     ((((((1213)))
     ++++232+++
Rahul Tapali
  • 9,887
  • 7
  • 31
  • 44

3 Answers3

7

Use Look ahead within your regex at the start..

/^(?=(.*\d){8,})[\d\(\)\s+-]{8,}$/
  ---------------
          |
          |->this would check for 8 or more digits

(?=(.*\d){8,}) is zero width look ahead that checks for 0 to many character (i.e .*) followed by a digit (i.e \d) 8 to many times (i.e.{8,0})

(?=) is called zero width because it doesnt consume the characters..it just checks


To restict it to 14 digits you can do

/^(?=([^\d]*\d){8,14}[^\d]*$)[\d\(\)\s+-]{8,}$/

try it here

Anirudha
  • 32,393
  • 7
  • 68
  • 89
  • 1
    Haha, first Some1.Kill.The.DJ beats me to the answer, then @JanDvorak beats me to the comment. :D So this is what I got: `^(?=(?:.*\d){8})(?:\d|-|\(|\)|\+|\s){12}` – Amadan Nov 28 '12 at 08:00
  • @Amadan you can't stop matching the main regex when you collect enough data. There might be undesired characters in the string. – John Dvorak Nov 28 '12 at 08:02
  • Also, I suggest you use rubular.com for Ruby queries - Ruby's regular expressions are quite a bit more powerful than JavaScript's, modifiers are different, and if that's not reason enough, Rubular has a quite nice interface. – Amadan Nov 28 '12 at 08:02
  • @JanDvorak: Good point. `^(?=(?:.*\d){8})(?:\d|-|\(|\)|\+|\s){12,}$` – Amadan Nov 28 '12 at 08:03
  • 1
    You can clean up the main part to: `[\d\s\(\)+-]{12,}` – pguardiario Nov 28 '12 at 08:07
  • You also don't need the `?` in the lookahead since you are already matching with `*`: `(?=(.*\d){8,})` – theon Nov 28 '12 at 08:18
  • Don't escape +- inside of [] though, do it like I do. – pguardiario Nov 28 '12 at 08:24
  • @Some1.Kill.The.DJ I checked you regex in rubular.com it is not matching for pattern '123456789' – Rahul Tapali Nov 28 '12 at 09:08
  • @clickit this is becuz i used `{12,}`..Use `{8,}` instead..check out the edit – Anirudha Nov 28 '12 at 09:10
  • @Some1.Kill.The.DJ can you explain this part: "(?=(.*\d){8,})" – Rahul Tapali Nov 28 '12 at 09:15
  • @Some1.Kill.The.DJ how do I restrict to maximum 14 digits. I tried this /^(?=(.*\d){8,14})[\d\(\)\s+-]{8,}$/ – Rahul Tapali Dec 05 '12 at 06:37
  • @Some1.Kill.The.DJ I written it in simple way: /^(?=(.*\d){8})(?!(.*\d){15})[\d\(\)\s+-]{8,}$/ . This works as what I want. Check is it correct regex. – Rahul Tapali Dec 05 '12 at 11:24
0

No need to mention ^, $, or the "or more" part of {8,}, or {12,}, which is unclear where it comes from.

The following makes the intention transparent.

r = /
  (?=(?:.*\d){8})    # First condition: Eight digits
  (?!.*[^-\d()+\s])  # Second condition: Characters other than `[-\d()+\s]` should not be included.
/x

resulting in:

"(1323  ++24)233" =~ r #=> 0
"24243434 43" =~ r #=> 0
"++++43435++4554345  434" =~ r #=> 0
"((((((1213)))" =~ r #=> nil
"++++232+++" =~ r #=> nil
sawa
  • 165,429
  • 45
  • 277
  • 381
0

Here's a non regular expression solution

numbers = ["(1323  ++24)233", "24243434 43" , "++++43435++4554345  434", "123 456_7"]

numbers.each do |number|
  count = 0
  number.each_char do |char| 
    count += 1 if char.to_i.to_s == char
    break if count > 7
  end
  puts "#{count > 7}"
end
Jonas Elfström
  • 30,834
  • 6
  • 70
  • 106