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
?CommentedAug 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.CommentedAug 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!)CommentedAug 3, 2011 at 20:32