Shell

轉義變數中的雙引號

  • February 8, 2018

我想將此命令放入一個文件中以便稍後執行:

ln -s "$xr"/ya.txt ~

我可以用(1)做到這一點:

cat > zu.sh <<eof
ln -s "$xr"/ya.txt ~
eof

或 (2):

printf 'ln -s "%s"/ya.txt ~\n' "$xr" > zu.sh

或 (3):

echo "ln -s '$xr'/ya.txt ~" > zu.sh

或 (4):

printf 'ln -s %q/ya.txt ~\n' "$xr" > zu.sh

或 (5):

printf 'ln -s "%s"/ya.txt ~\n' "${xr//\"/\\\"}"

然而,每個解決方案都是有問題的。如果 (1) 或 (2) 中的變數包含雙引號,它們將失敗;如果 (3) 中的變數包含單引號,它將失敗。(4) 很好,但不是由 POSIX 定義的。(5) 是好的,但是是 Bashism。看起來最好的選擇是使用 (1) 或 (2) 並轉義變數中的任何雙引號,但這可以通過其他方式完成嗎?

我認為這是安全的:

esc() {
   printf "%s\n" "$1" | sed -e "s/'/'\"'\"'/g" -e "1s/^/'/" -e "\$s/\$/'/"
}

它對字元串進行單引號,因此輸入字元串中的任何$, ```, \, and"都無關緊要,並將任何現有'字元轉換為'"'"'(即結束單引號,雙引號一個單獨的單引號,然後重新輸入單引號)。

$(...)在那裡使用命令替換很誘人,除了它會吃掉輸入中的任何尾隨換行符。相反,開始和結束引號由第二個和第三個sed腳本本身插入,在第一行的開頭和最後一行的結尾。任何嵌入的換行符都是原始的,這很好。

輸出適合複製回 shell,即使在我可以發明的最病態的情況下(首先使用Bash ANSI-C 引用$'...'來創建測試字元串,但不是之後):

bash-4.4$ esc $'abc\ndef ghi\'jkl$mno`pqr\\stu\\\'vwx\n\n\n'
'abc
def ghi'"'"'jkl$mno`pqr\stu\'"'"'vwx


'
bash-4.4$ echo 'abc
> def ghi'"'"'jkl$mno`pqr\stu\'"'"'vwx
>
>
> '
abc
def ghi'jkl$mno`pqr\stu\'vwx



bash-4.4$ dash
$ echo 'abc
def ghi'"'"'jkl$mno`pqr\stu\'"'"'vwx


'> > > >
abc
def ghi'jkl$mno`pqr\stu\'vwx



$

將其放入變數中是安全的xr=$(esc "$xr"),然後稍後在您的此處文件或其他地方進行普通替換。

引用自:https://unix.stackexchange.com/questions/422165