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.
2 Answers
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")'"
-
+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
? Commented Aug 4, 2011 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. Commented Aug 4, 2011 at 16:14
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
-
2Always 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!) Commented Aug 3, 2011 at 20:32