Let’s set up an example use case for regular expressions:
'1234 St Peter St, Ste 12'.sub(/(.*)\bst\b/i, '\1Street')
# => "1234 St Peter Street, Ste 12"
\1
matches “1234 St Peter “.\1Street
essentially says, “Replace '1234 St Peter St' with '1234 St Peter ' + 'Street'.”So obviously there are more street types than just street. What about streets and lanes and courts and boulevards? How do we handle all of those? Let’s extend our regex to make it match any of these, and test it on “1234 St Mary Ave”…
'1234 St Mary Ln'.sub(/(.*)\b(st|ct|ln|blvd)\b/i, '\1Street')
# => "1234 St Mary Street"
Oops, now “St Mary” is a street, not a lane. We need to use a different replacement depending on the abbreviation. For this, we’ll have to make a few changes.
\2
.)sub
‘s block syntax in place of '\1Street'
that we have now.expansions = {
'st' => 'Street',
'ct' => 'Court',
'ln' => 'Lane',
'blvd' => 'Boulevard',
}
pattern = /(.*)\b(#{expansions.keys.join('|')})\b/i # => st|ct|ln|blvd
With block syntax, capture groups become available as block variables $1
, $2
, etc. Using $2
we can look up the correct expansion to substitute for the given street abbreviation.
"1234 St Peter's State Blvd Ste E".sub(pattern) do
"#{$1}#{expansions[$2.downcase]}"
end
# => "1234 St Peter's State Boulevard Ste E"