我有一个变量,例如a'b
,包含一个单引号,在将其写入文件之前,我需要将其替换为两个单引号:a''b
。
以下 bash 代码用于为我完成工作......
line="a'b"
echo "${line//\'/\'\'}" > out.txt
...直到今天我发现不同的输出取决于所使用的 bash 版本:
- GNU bash,版本 4.3.48(1)-release (x86_64-pc-linux-gnu):
a''b
- GNU bash,版本 4.2.46(2)-release (x86_64-redhat-linux-gnu):
a\'\'b
我尝试以多种方式修改上面的行,但无法让它a''b
在两个 bash shell 中产生相同的输出。
echo
我最终使用了和的组合sed
,
echo "$(echo $line | sed "s/'/''/g")" > out.txt
但我仍然想知道是否可以使用更简洁的纯 bash 表达式来完成这项工作。它可以?
答案1
中的一个变化bash-4.3-alpha 和之前的版本 bash-4.2-release 之间:
当使用模式替换单词扩展时,bash 现在通过删除引号来运行替换字符串,因为它允许该字符串中的引号充当转义字符。这不向后兼容,因此可以通过将 bash 兼容模式设置为 4.2 来禁用它。
输入:
BASH_COMPAT=4.2
line="a'b"
echo "${line//\'/''}"
输出:
a''b
答案2
对于无论版本如何都可以工作的方法(以及 shell 实现,如它来自的 ksh93 以及也支持它的 mksh 和 zsh),您可以将模式和替换存储在变量中:
pattern="'"
replacement="''"
printf '%s\n' "${line//$pattern/$replacement}"
或者
q="'"
printf '%s\n' "${line//$q/$q$q}"
(请注意,在 中zsh
,$pattern
被视为固定字符串。如果您希望将其视为通配符模式(此处不适用,因为$pattern
不包含通配符),则需要替换$pattern
为$~pattern
。在其他 shell 中,如果想$pattern
作为固定字符串,需要用引号( ${line//"$pattern"/$replacement}
) 括起来。