The pattern to match those characters is easy:
/[\d .-]+/
http://rubular.com/r/hSj7okaji3
You can make it a little more comprehensive and look for digits and separators in certain positions:
/6(?:\d{8}|\d{2}[ .-](?:\d{2}[ .-]){2}\d{2})/
http://rubular.com/r/HkSp8qk0ph
For instance:
strings = [
'foo 623456789 bar',
'foo 123456789 bar',
'foo 623 45 67 89 bar',
'foo 123 45 67 89 bar',
'foo 623.45.67.89 bar',
'foo 123.45.67.89 bar',
'foo 623-45-67-89 bar',
'foo 123-45-67-89 bar',
]
found_pns = strings.select{ |s| s[/6(?:\d{8}|\d{2}[ .-](?:\d{2}[ .-]){2}\d{2})/] }
# => ["foo 623456789 bar",
# "foo 623 45 67 89 bar",
# "foo 623.45.67.89 bar",
# "foo 623-45-67-89 bar"]
Once you have the numbers, typically you should normalize them prior to storing in a database:
found_pns.map{ |s| s[/6(?:\d{8}|\d{2}[ .-](?:\d{2}[ .-]){2}\d{2})/].tr(' .-', '') }
# => ["623456789", "623456789", "623456789", "623456789"]
Once you've done that, then you format them as needed when you get ready to display them:
pn = "623456789".match(/(?<n1>\d{3})(?<n2>\d{2})(?<n3>\d{2})(?<n4>\d{2})/)
# => #<MatchData "623456789" n1:"623" n2:"45" n3:"67" n4:"89">
(I'm using named captures above, but that's just to illustrate how the values are retrieved.)
"%s-%s-%s-%s" % [*pn.captures] # => "623-45-67-89"
or:
pn.captures.join('-') # => "623-45-67-89"