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

Bas*_*ian 5 bash escape-characters

我有一个变量,例如a'b,包含一个单引号,在将其写入文件之前,我需要将其替换为两个单引号:a''b.

以下 bash 代码用于为我完成工作......

line="a'b"
echo "${line//\'/\'\'}" > out.txt
Run Code Online (Sandbox Code Playgroud)

...直到今天,我发现根据所使用的 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
Run Code Online (Sandbox Code Playgroud)

但我仍然想知道是否可以使用更简洁的纯 bash 表达式来完成这项工作。它可以?

Kam*_*ski 7

其中一个变化的bash-4.3-α,和以前的版本时,bash-4.2版本之间:

当使用模式替换词扩展时,bash 现在通过引号删除来运行替换字符串,因为它允许该字符串中的引号充当转义字符。这不是向后兼容的,因此可以通过将 bash 兼容模式设置为 4.2 来禁用它。


输入:

BASH_COMPAT=4.2
line="a'b"
echo "${line//\'/''}"
Run Code Online (Sandbox Code Playgroud)

输出:

a''b
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 5

对于无论版本如何都可以工作的方法(以及它来自的 ksh93 和 mksh 和 zsh 之类的 shell 实现,它们也支持它),您可以将模式和替换存储在变量中:

pattern="'"
replacement="''"
printf '%s\n' "${line//$pattern/$replacement}"
Run Code Online (Sandbox Code Playgroud)

或者

q="'"
printf '%s\n' "${line//$q/$q$q}"
Run Code Online (Sandbox Code Playgroud)

(请注意,在 中zsh,the$pattern被视为固定字符串。如果您希望将其作为通配符模式(此处不适用,因为$pattern不包含通配符),则需要替换$pattern$~pattern。在其他 shell 中,如果你想$pattern 被当作​​一个固定的字符串,你需要把它加引号(${line//"$pattern"/$replacement})。