Shell
轉義變數中的雙引號
我想將此命令放入一個文件中以便稍後執行:
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")
,然後稍後在您的此處文件或其他地方進行普通替換。