Bash

轉義變數以用作另一個腳本的內容

  • June 9, 2021

這個問題不是關於如何編寫正確轉義的字元串文字。我找不到任何與如何轉義變數以在腳本或其他程序中直接使用的相關問題。

我的目標是使腳本能夠生成其他腳本。這是因為生成的腳本中的任務將在另一台機器上執行 0 到n次,並且生成它們的數據可能在它們執行之前(再次)發生變化,因此直接通過網路執行操作將不行。

給定一個可能包含特殊字元(例如單引號)的已知變數,我需要將其寫為完全轉義的字元串文字,例如,foo包含的變數bar'baz應在生成的腳本中顯示為:

qux='bar'\''baz'

這將通過附加"qux=$foo_esc"到腳本的其他行來編寫。我是這樣使用 Perl 做到的:

foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"

但這似乎有點矯枉過正。

我單獨使用 bash 沒有成功。我已經嘗試了很多變體:

foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"

但是輸出中會出現額外的斜杠(當我這樣做時echo "$foo"),或者它們會導致語法錯誤(如果從 shell 完成則期望進一步的輸入)。

對於這種情況,Bash 有一個參數擴展選項

${parameter@Q}擴展是一個字元串,它是以可重複用作輸入的格式引用的參數值。

所以在這種情況下:

foo_esc="${foo@Q}"

這在 Bash 4.4 及更高版本中受支持。其他形式的擴展也有幾個選項,以及專門生成完整的賦值語句 ( @A)。

Bash 提供了一個帶有格式說明符的printf內置函式,即使在舊 (<4.0) 版本的 Bash 中,它也會為您執行 shell 轉義:%q

printf '[%q]\n' "Ne'er do well"
# Prints [Ne\'er\ do\ well]

printf '[%q]\n' 'Sneaky injection $( whoami ) `ls /root`'
# Prints [Sneaky\ injection\ \$\(\ whoami\ \)\ \`ls\ /root\`]

這個技巧也可以用來從函式返回數據數組:

function getData()
{
 printf '%q ' "He'll say hi" 'or `whoami`' 'and then $( byebye )'
}

declare -a DATA="( $( getData ) )"
printf 'DATA: [%q]\n' "${DATA[@]}"
# Prints:
# DATA: [He\'ll\ say\ hi]
# DATA: [or\ \`whoami\`]
# DATA: [and\ then\ \$\(\ byebye\ \)]

請注意,內置 Bash與大多數類 Unix 作業系統捆綁printf的實用程序不同。printf如果由於某種原因,該printf命令呼叫實用程序而不是內置命令,則您始終可以builtin printf改為執行。

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