1

I was trying to find strings out which is followed by only "..",but couldn't get that :

["..ab","...cc","..ps","....kkls"].each do |x|
puts x if /../.match(x)
end
..ab
...cc
..ps
....kkls
=> ["..ab", "...cc", "..ps", "....kkls"]

["..ab","...cc","..ps","....kkls"].each do |x|
puts x if /(.)(.)/.match(x)
 end
..ab
...cc
..ps
....kkls
=> ["..ab", "...cc", "..ps", "....kkls"]

Expected output:

["..ab","..ps"]
DoLoveSky
  • 777
  • 1
  • 6
  • 17

5 Answers5

5

What you want is

/^\.\.(?!\.)/

The caret ^ at the beginning means match the beginning of the string; periods must be escaped by a backslash as \. because in regular expressions a plain period . matches any character; the (?!\.) is a negative look-ahead meaning the next character is not a period. So the expression means, "at the beginning of the string, match two periods, which must be followed by a character which is not a period."

>> /^\.\.(?!\.)/.match "..ab"
=> #<MatchData "..">
>> /^\.\.(?!\.)/.match "...cc"
=> nil
  • Could you explain the code of your one how works in such matching? – DoLoveSky Feb 04 '13 at 21:01
  • 1
    \. because you have to escape the dot (is like * for regexp, selects anything). So basically is "string_start:dot dot (not dot) anything else" read some regexp basics is easy. Also some regexp negation: http://stackoverflow.com/questions/3977455/how-do-i-turn-any-regex-into-an-complement-of-itself-without-complex-hand-editin – MGP Feb 04 '13 at 21:03
2

Try selecting on /^\.\.[^\.]/ (starts with two dots and then not a dot).

ss = ["..ab","...cc","..ps","....kkls"]
ss.select { |x| x =~ /^\.\.[^\.]/ } # => ["..ab", "..ps"] 
maerics
  • 151,642
  • 46
  • 269
  • 291
2

Try using /^\.{2}\w/ as the regular expression.

A quick explanation: ^ means the start of the string. Without this, it can match dots that are found in the middle of the string.

\. translates to . -- if you use the dot on its own, it will match any non-newline character

{2} means that you're looking for two of the dots. (you could rewrite /\.{2}/ as /\.\./)

Finally, the \w matches any word character (letter, number, underscore).

A really good place to test Ruby regular expressions is http://rubular.com/ -- it lets you play with the regex and test it right in your browser.

graysonwright
  • 514
  • 2
  • 8
1

You don't need regex for this at all, you can just extract the appropriate leading chunks using String#[] or String#slice and do simple string comparisons:

>> a = ["..ab", "...cc", "..ps", "....kkls", ".", "..", "..."]
>> a.select { |s| s[0, 2] == '..' && s[0, 3] != '...' }
=> ["..ab", "..ps", ".."]
mu is too short
  • 426,620
  • 70
  • 833
  • 800
0

Maybe this:

["..ab","...cc","..ps","....kkls"].each {|x| puts x if /^\.{2}\w/.match(x) }

Or if you want to make sure the . doesn't match:

["..ab","...cc","..ps","....kkls"].each {|x| puts x if /^\.{2}[^\.]/.match(x) }
rainkinz
  • 10,082
  • 5
  • 45
  • 73