4

Part of the Korn script I am writing requires that I replace all occurrences of the ' character with two occurrences (''). I am trying to log some SQL that I am generating in this script to a column in another table but single quotes need to be replaced with 2 instances of the single quote character. I know there must be examples of this functionality somewhere but I'm not finding a string replace example specific to variables anywhere.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Ben
  • 205
  • 1
  • 4
  • 6

2 Answers2

7

In ksh93 and zsh, there's a string replacement construct ${VARIABLE//PATTERN/REPLACEMENT}, used twice in the following snippet: once to replace ' by '' and once to replace newlines by '+char(10)+'. If there are no newlines in the input string, you can omit the second assignment command.

quoted_string=\'${raw_string//\'/\'\'}\'
quoted_string=${quoted_string//$'\n'/"'+char(10)+'"}

This construct is also available in bash, but the quoting rules are different. The following snippet works in all of ksh93, bash and zsh.

quoted_string=\'${raw_string//$'\''/$'\'\''}\'
quoted_string=${quoted_string//$'\n'/$'\'+char(10)+\''}

In ksh88 and other shells, you need to write a relatively complex loop to replace the single quotes one at a time. The following snippet doubles single quotes, but leaves newlines unchanged).

q="$raw_string"; quoted_string=
while
    quoted_string="$quoted_string'${q%%\'*}'"
    case "$q" in *\'*) q="${q#*\'}";; *) false;; esac
do :; done

Alternatively, you can use sed. Be careful when feeding the data to sed, as echo doesn't always print its argument as-is.

quoted_string="'$(printf '%s\n' "$raw_string" |
                  sed -n -e "s/'/''/g" -e 'H' \
                      -e '$ g' -e 's/^\n//' -e "s/\\n/'+char(10)+'/g" -e '$ p')'"

If there are no newlines in the string, the following much simpler sed command suffices.

quoted_string="'$(printf '%s\n' "$raw_string" | sed -e "s/'/''/g")'"
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • +1. With the last example, I'm getting the warning "sed: Missing newline at end of file standard input." -- do you mean `printf "%s\n"` instead of `%s`? – glenn jackman Aug 04 '11 at 15:09
  • @glenn Yes (I tested but with GNU sed which doesn't care about final newlines). Thanks for that; also your comment made me realize it would be a good idea to replace with newlines in the input string, even if this wasn't in Ben's question. – Gilles 'SO- stop being evil' Aug 04 '11 at 16:14
-1

Is there any particular reason you couldn't call sed from within your ksh script?

This simple script:

#!/bin/ksh

foo="left ' right"
echo $foo
foo=$(echo "$foo" | sed "s#\'#\'\'#g")
echo $foo

gives me this output:

left ' right
left '' right
bahamat
  • 38,658
  • 4
  • 70
  • 103
  • 2
    Always double quote variable substitutions. As written, this mangles whitespace and shell wildcard characters; that leaves ample holes for an attacker. @Ben **do not use this code, it's broken.** (I usually fix rather than downvote in such cases, but this is a question about quoting!) – Gilles 'SO- stop being evil' Aug 03 '11 at 20:32