1

I want to use backticks in ruby for a programm call. The parameter is a String variable containing one or more backticks, i.e. "&E?@@A`?". The following command yields a new label as its return value:

echo "&E?@@A\`?" | nauty-labelg 2>/dev/null

From a ruby program I can call it as follows and get the correct result:

new_label = `echo "&E?@@A\\\`?" | nauty-labelg 2>/dev/null`

I want to achieve the same using a variable for the label. So I have to insert three slashes into my variable label = "&E?@@A`?" in order to escape the backtick. The following seems to work, though it is not very elegant:

escaped_label = label.gsub(/`/, '\\\`').gsub(/`/, '\\\`').gsub(/`/, '\\\`')

But the new variable cannot be used in the program call:

new_label = `echo "#{escaped_label}" | nauty-labelg 2>/dev/null`

In this case I do not get an answer from nauty-labelg.

Razneesh
  • 1,147
  • 3
  • 13
  • 29
ewi
  • 175
  • 1
  • 9
  • 2
    `require 'shellwords'` and use `\`echo #{label.shellescape} | ...\`` – Stefan Mar 13 '20 at 16:39
  • Yay, that works! Thanks a lot, Stefan, you saved my day :) – ewi Mar 13 '20 at 16:43
  • 2
    `new_label, status = Open3.capture2('nauty-labelg', stdin_data: label)` would be another, maybe cleaner option. – Stefan Mar 13 '20 at 16:44
  • Yes, that is a nice solution, but not for nauty, since it complains a missing newline and even if it succeeds there is some output stuff I got rid of by /dev/null. Anyhow, thanks also for this hint for future work, I hadn't been aware of these packages. – ewi Mar 13 '20 at 18:08
  • The title and first sentence contain typos. Please correct and proof your text in future. – Cary Swoveland Mar 13 '20 at 18:31

1 Answers1

0

So I have to insert three slashes into my variable label = "&E?@@A`?" in order to escape the backtick.

No, you only need to add one backslash for the output. To escape the ` special bash character. The other other two are only for representation proposes, otherwise it isn't valid Ruby code.

new_label = `echo "&E?@@A\\\`?" | nauty-labelg 2>/dev/null`

The first backslash will escape the second one (outputting one single backslash). The third backslash escapes the ` character (outputting one single `).

You should only add backslashes before characters that have a special meaning within double quoted bash context. These special characters are: $, `, \ and \n. Those can be escaped with the following code:

def escape_bash_string(string)
  string.gsub(/([$`"\\\n])/, '\\\\\1')
end

For label = "&E?@@A`?" only the ` should be escaped.

escaped_string = escape_bash_string("&E?@@A\`?")
puts escaped_string
# &E?@@A\`?
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • Do you mean %x{...}? I tried it before asking but it cannot handle a backtick in the lable, even with your escape_bash_string since that will only insert two backslashes and I need three of them. – ewi Mar 14 '20 at 09:55
  • There should only be one backslash, since you expect the `&E?@@A\\`?` output. `\`echo "&E?@@A\\\\`?" | nauty-labelg 2>/dev/null\`` evaluates to a single backslash, since the first escapes the second, and the third escapes the `\`` (like I mentioned in the answer). – 3limin4t0r Mar 14 '20 at 18:16