1

I am trying to build a linux sendemail command in R using paste from a bunch of values from a contact form. The message portion will have single and/or double quotes in it. Based on this post (How to escape double quote inside a double quote?) I have determined that I need to finish already opened one ('), placing escaped one (\'), then opening another one (').

For example, this works when run directly from linux command line (when using actual email addresses):

sendemail -f mary@test.com -t bob@test.com -u 'Subject here' -m 'My message'\''s text has single quote or maybe "double quotes".' -s smtp.gmail.com:587 -o tls=yes -xu from@mail.com -xp xxxxxx

The message portion is coming from a contact form and I want to email that message to our team. I've tried using gsub to replace a single quote with '\'' so sendemail will send the message successfully but I have not found the correct gsub syntax. I've tried various gyrations of this type of thing:

gsub("'", "'\''", message)

gsub("\'", "'\\''", message)

and so on... I've tried using fixed, perl, etc. I cannot seem to get the needed syntax.

I get either no backslashes or 2 backslashes and sendemail wants only one backslash.

Certainly, I can just remove the single and double quotes from the message and it will work. I would prefer to preserve the message "as is" if possible, though.

Is this even possible with gsub and paste?

Here is a code snippet of what I'm doing:

 message = gsub("\'", "\\\'", input$mailAndStoreModalText)
 message = gsub("\"", "\\\"", message)
 print( message)

If my input is - This's the "best" music - the gsubs above just result in the same exact thing with 0 backslashes. Then this fails:

team.email = paste0("sendemail -f ", user.email, 
                   " -t ", distr.list,
                   " -u 'Contact Form Submitted' -m", 
                   " 'Priority: ", priority," ", message, 
                   "' -s smtp.gmail.com:587 -o tls=yes -xu sender@test.com -xp xxxxx")

 t <- try(system(team.email, intern = TRUE))
Mary
  • 65
  • 6
  • 1
    What are you trying to do? Replace all `"` with ``\"`` and `'` with ``\'``? – Wiktor Stribiżew Nov 16 '17 at 21:05
  • sendemail has quoted portions. The message text is denoted by -m "message text". If the message text has quotes, too, then those nested quotes must be escaped. It seems that the linux command wants nested quotes to be escaped in this manner: close the first quote, use \ before the embedded quote and then reopen the quote. (per that link I referenced). And I have found that to work. But I cannot get R to produce that for me using gsub and paste. When trying to escape the quote using gsub it always gives me either 0 backslashes or 2 backslashes and I need 1 for sendemail to work. – Mary Nov 17 '17 at 11:16
  • Mary, what piece of code gives you 2 backslashes? I am 100% sure you do not get 2 ``\``s, you just do not understand that what you see is actually a single ``\``. – Wiktor Stribiżew Nov 17 '17 at 11:25
  • Just for you to see and feel the difference, see https://ideone.com/3HJpL4, `gsub("\"", "\\\"", x, fixed=TRUE)` replaces all `"` with ``\"``. – Wiktor Stribiżew Nov 17 '17 at 11:33
  • To escape single quotes - `gsub("'", "\\'", y, fixed=TRUE)`. – Wiktor Stribiżew Nov 17 '17 at 11:44
  • Thank you for your help. I really appreciate it. I edited my original post to hopefully better explain the issue I'm having. – Mary Nov 17 '17 at 12:24
  • You must use [`message <-gsub("\"", "\\\"", gsub("\'", "\\\'", input$mailAndStoreModalText, fixed=TRUE), fixed=TRUE)`](https://ideone.com/r0KRj1) – Wiktor Stribiżew Nov 17 '17 at 12:27

1 Answers1

1

If you chain the gsubs, you should pass message variable the second time. However, you may use it like this:

message <- gsub("\"", "\\\"", gsub("\'", "\\\'", input$mailAndStoreModalText, fixed=TRUE), fixed=TRUE)

Or a regex based replacement:

message <- gsub("([\"'])", "\\\\\\1", input$mailAndStoreModalText)

Both will output This\'s the \"best\" music as output.

See the R demo online. Note that cat(message, "\n") command shows you the literal string that message holds, not the string literal that you get when trying to just print message.

Also, the ([\"']) regex matches and captures into Group 1 either a " or ' and the "\\\\\\1" replacement pattern replaces the whole match with \ (that is defined with 4 backslashes) and then the value inside Group 1 (\\1).

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Yeah, I should be more careful with my copy/paste. I am using message in the 2nd gsub. And I just tried: message <- gsub("([\"'])", "\\\\\\1", input$mailAndStoreModalText) cat(message, "\n") And I'm still getting 0 backslashes. Could it be that this code is in a shiny module? I wouldn't think so but ya never know. This is the most frustrating thing because it "should" work. – Mary Nov 17 '17 at 12:43
  • @Mary Then, there are no quotes. Or there are *curly* or other Unicode quotes. Have a look at [this answer of mine](https://stackoverflow.com/questions/47173557/text-mining-r-package-regex-to-handle-replace-smart-curly-quotes/47173868#47173868). – Wiktor Stribiżew Nov 17 '17 at 12:47
  • [This code](https://ideone.com/SJVP8E) works in Windows, output is `-\‟m\” \„message\” \'\ʽtext\’\'\"` for `x <- "-‟m” „message” 'ʽtext’'\""` – Wiktor Stribiżew Nov 17 '17 at 12:54
  • Thank you so much for your help. I don't have it working yet but I'm sure I will be able to. That other post you referenced is awesome and is very helpful. You've obviously put a lot of time in working with gsub and special chars. I now know why some of my search/replaces don't seem to work. It was the curly quotes! I'm going with this for now: sngl_quot_rx = "['ʻʼʽ٬‘’‚‛՚︐]" dbl_quot_rx = "[““”‟〝〞"″‶]" message = gsub(sngl_quot_rx, "", `Encoding<-`(input$mailAndStoreModalText, "UTF8")) message = gsub(dbl_quot_rx, "", `Encoding<-`(message, "UTF8")) – Mary Nov 17 '17 at 13:46
  • @Mary Are you working in Windows or Linux? Or MacOS? [This demo](https://ideone.com/4czqdW) is working well, just add those quotes you need into the bracket expression. – Wiktor Stribiżew Nov 17 '17 at 13:53
  • @Mary Glad it worked for you. Please also consider upvoting if my answer proved helpful to you (see [How to upvote on Stack Overflow?](http://meta.stackexchange.com/questions/173399/how-to-upvote-on-stack-overflow)). Remember you cannot upvote more than 2 answers belonging to one user per day. Else, the upvotes will be revoked the next day. – Wiktor Stribiżew Nov 17 '17 at 13:56
  • I'm working on a mac but the code is running on an AWS EC2 instance with Ubuntu. – Mary Nov 17 '17 at 14:08
  • @Mary Thumbs-up :) I went to a AWSome Day yesterday, this is an incredible technology. – Wiktor Stribiżew Nov 17 '17 at 14:09