bash:用字符串中的两个引号替换单引号

bash:用字符串中的两个引号替换单引号

我有一个变量,例如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}) 括起来。

相关内容