Q:

Convert single quotes (apostrophe) in a string to correct opening and closing quotes

I have strings that contain some single quotes (') and I'd like to educate the quotes (ie turn them into ‘ and ’. My regex on this (peculiar) test string is giving me some problems:
s = "'Twas the night before Christmas. 'Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!' 
      This is 'tricky' aka 'It's not easy'. Or 'Non-trivial'. "
s = replace(s, r"\B'\b([^'\r\n]+)\b'\B" => s"‘\1’")
s = replace(s, r"(\w)'(\w)" => s"\1’\2")
println(s)

The correct output should be:

’Twas the night before Christmas. ‘Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!' 
  This is ‘tricky’ aka ‘It’s not easy’. Or ‘Non-trivial’. "

but I'm only catching some of them:

'Twas the night before Christmas. 'Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!' 
  This is ‘tricky’ aka 'It’s not easy'. Or ‘Non-trivial’. 

Any help from Julia/regex ‘wizards’ would be appreciated!

A:

Contractions with a ' at the beginning are a bit of a problem and require special casing. 
You also seem to have a typo in your desired output (Świerk!' instead of Świerk!’)
The following function should work in most cases:
function educate(s)
    s = replace(s, r"'(?=twas|twere|til|tis)"i => s"’") # handle contractions with a ' at the beginning
    s = replace(s, r"(\w)'(\w)" => s"\1’\2") # handle normal contractions
    s = replace(s, r"s'" => s"s’") # this is either something like "the girls' toys" or the end of a quote, but we don't care
    s = replace(s, r"(?<=[\s\,\.])'(?=\S)(.+?)(?<!\s)'(?=[\s\,\.])" => s"‘\1’") # quotations where the right side doesn't end with an "s'"
    s = replace(s, r"'" => s"‘") # everything we haven't caught yet should be a "‘"
    s
end

# Your test case:
s = "'Twas the night before Christmas. 'Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!' This is 'tricky' aka 'It's not easy'. Or 'Non-trivial'."
target = "’Twas the night before Christmas. ‘Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!’ This is ‘tricky’ aka ‘It’s not easy’. Or ‘Non-trivial’."
educate(s) == target # true

# Slightly trickier:
s = " 'Twas the night before Christmas. 'Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!' This is 'tricky' aka 'It's not easy'. Or 'Non-trivial'. 'The girls' teachers' stuffs'"
target = " ’Twas the night before Christmas. ‘Pchnąć w tę łódź jeża Żywioł, jaźń, Świerk!’ This is ‘tricky’ aka ‘It’s not easy’. Or ‘Non-trivial’. ‘The girls’ teachers’ stuffs’"
educate(s) == target # true

