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.
- 807,993
- 194
- 1,674
- 2,175
- 205
- 1
- 4
- 6
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")'"
- 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
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
- 38,658
- 4
- 70
- 103
-
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!) – Gilles 'SO- stop being evil' Aug 03 '11 at 20:32