Shell

引用嵌套參數擴展的正確方法是什麼?

  • December 11, 2019

在處理嵌套參數擴展時,以下哪一種是正確的引用方式?

這個:

var="${var#"${var%%[![:space:]]*}"}"

或者這個:

var="${var#${var%%[![:space:]]*}}"

我已經看到它是雙向的。第一個變體是來自Stack Overflow 答案的片段。這是對該問題最受好評的答案之一(問題是關於如何從變數中修剪空白)。


我也很難找到一個有信譽的來源來解決如何在使用作為變數而不是文字文本的“單詞”或“模式”時引用事物。下面兩個,哪個是正確的?

這個:

strip_ext="${filename%."$filename_ext"}"

或者這個:

strip_ext="${filename%.$filename_ext}"

在這兩種情況下,第一種方法通常是您想要的。當右側的字元串${var#*a}沒有被引用時,它被解釋/擴展為模式。在此範例中,刪除前導文本直到第一個字母a。如果引用:${var#"*a"}擴展將刪除文字*a. 如果在以下情況下,這可能是一個問題:

"${filename%."$filename_ext"}"

可能包含"$filename_ext"模式字元。同樣,如果$varin"${var#"${var%%[![:space:]]*}"}"可以包含模式字元 (*?[) 並且您不希望它們被解釋為模式,則將擴展引用為:

"${var#"${var%%[![:space:]]*}"}"

請注意,變數賦值的右側被認為是帶引號的,不需要(但不會造成傷害)引號,這兩個也是正確的:

     var=${var#"${var%%[![:space:]]*}"}
strip_ext=${filename%."$filename_ext"}

這似乎取決於您希望如何解釋擴展的右側。作為模式,或作為文字字元串。

在這裡,未引用*的是一個模式,並且吃掉了整個字元串。引用的只是刪除了一個字面星號:

var='foo*'
echo ":${var%%*}:"                 # this prints ::
echo ":${var%%"*"}:"               # this prints :foo:

如果將模式放入變數中也是一樣的:

var='foo*'
pat='*'
echo ":${var%%$pat}:"              # this prints ::
echo ":${var%%"$pat"}:"            # this prints :foo:

或者在右側使用另一個參數擴展:

var='foo*'
pat='x*x'
echo ":${var%%${pat//x}}:"         # this prints ::
echo ":${var%%"${pat//x}"}:"       # this prints :foo:

${pat//x}結果*再次出現。)

我嘗試過的所有類似 POSIX 的 shell(Bash、ksh、yash)都得到了相同的行為。Zsh 當然是不同的,右側的所有參數擴展都像在那裡引用一樣,就像它們在分詞問題上所做的那樣。我想有一些運算符可以在擴展中使用來改變它。

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