I seem to be running into an issue that's specific to ksh88 that's changing single quotes to double quotes, but only under certain situations involving heredocs and command substitution.
Here's an example:
#!/bin/ksh
# This example works correctly
echo "Example 1:"
cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF
echo
# This example is broken
echo "Example 2:"
var=$(cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF)
echo "${var}"
echo
# This example works correctly
echo "Example 3:"
var=`cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF`
echo "${var}"
echo
And here's the output (note how Example 2 is different):
Example 1:
The 'quick' brown fox "jumped" over the lazy dog.
Example 2:
The "quick" brown fox "jumped" over the lazy dog.
Example 3:
The 'quick' brown fox "jumped" over the lazy dog.
The '
to "
substitution seems to occur before the command runs. In actual context, the heredoc is passing SQL to Oracle. By changing '
to "
, strings are being converted to identifiers, thus breaking the SQL. This can also be observed by enabling xtrace during execution of the above code.
How can I prevent the '
to "
conversion in the above code snippet without using backticks?
Edit: The plot thickens. Replacing the command substituion $( ... )
with backtick notation doesn't replace the single quotes with double quotes. So (optional) question two: why?
Use the String. replace() method to replace double with single quotes, e.g. const replaced = str. replace(/"/g, "'"); . The replace method will return a new string where all occurrences of double quotes are replaced with single quotes.
' End first quotation which uses single quotes. " Start second quotation, using double-quotes. ' Quoted character. " End second quotation, using double-quotes.
A single quote is not used where there is already a quoted string. So you can overcome this issue by using a backslash following the single quote.
Single quotes won't interpolate anything, but double quotes will. For example: variables, backticks, certain \ escapes, etc. Enclosing characters in single quotes ( ' ) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
Here are my notes when I discovered this same bug several years ago.
Test script:
#!/bin/ksh
cat <<EOF
$PWD "$PWD" '$PWD'
EOF
echo `cat <<EOF
$PWD "$PWD" '$PWD'
EOF
`
echo $(cat <<EOF
$PWD "$PWD" '$PWD'
EOF
)
Output for different shells:
(NOTE: works as expected)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
(NOTE: single quotes replaced with double quotes and variable not substituted)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" "$PWD"
Work-around:
Compute the single-quoted string externally from the here-file
abc=xyz
STR="'$abc'"
x=$( cat <<EOF
$abc "$abc" $STR
EOF
)
Use the here-file in a function instead of directly
fn() {
cat <<EOF
$abc "$abc" '$abc'
EOF
}
abc=xyz
x=$(fn)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With