Bash

Bash 不執行分詞和萬用字元的上下文是什麼?

  • July 22, 2020

在這些情況下,Bash 不會在萬用字元中執行分詞:

  • 賦值的 LHS 或 RHS,索引數組除外
var=$value                                # simple variable
declare -A hash
key="key with a space"
hash[$key]=$value                         # index of an associative array

arr=$(echo "1 2 3")                       # word splitting does happen here
  • 裡面[[ ]]
var="one two"
if [[ $var = *" "* ]]; then ...           # check if var has a space in it
if [[ $(echo "one two") = $var ]]; then   # use the output of command substitution to compare with var
  • 裡面(( ))
((sum = $(echo "99 + 1")))                  # assigns 100 to sum
  • 在這裡字元串
cat <<< *                                 # gives '*' as the output

是否有明確的 Bash 執行或不執行分詞和通配的情況列表?

這通常是它不能或沒有意義的情況,因此非列表上下文。但是,它在非列表上下文中執行此操作,但是當它導致多個項目或將這些項目與空格連接時會抱怨。

此外,重要的是要區分萬用字元模式匹配和文件名生成或通配,即生成與模式匹配的文件名列表。

例如 in [[ foo = * ]],沒有 globbing,因為它*沒有擴展到目前目錄中的非隱藏文件列表,但*仍被解釋為模式(這裡它返回 true與模式foo匹配*)。

通過這裡的拆分,我們指的是在不帶引號的參數擴展 ( $param)、命令替換 ( $(...)and ...) 和算術擴展 ( $((...))and $[...]) 上使用列表上下文中$IFS的特殊參數進行的隱式拆分。

我們將在*下面舉個例子。作為一種模式,它匹配任何字元序列。作為一個 glob,它擴展到目前目錄中的所有非隱藏文件(服從dotglob, GLOBIGNORE…)。

以下適用於bash,其他外殼有變化。

不會發生拆分和通配的情況:

  • 引用時(帶'*', "*", \*, $'*', $"*")。
  • 在此處的文件中(無論是否引用分隔符):
cat << EOF
*
EOF
cat << 'EOF'
*
EOF
  • 內部算術表達式:

    • echo $((2 * 2))*不是 globbed 而是$((...))經歷 split+glob,嘗試之後IFS=4
    • array[2 * 2]=4// . ${array[2 * 2]}_ exec {array[2*2]}>&1請注意,您需要unset -v 'a[1]'([1]是萬用字元) 中的引號。
    • ((2 * 2))
    • echo $[2 * 2]
  • 標量變數賦值:

    • var=*
    • array[x]=*
    • hash[key]=*
    • array=([1]=*)(例如,舊版本的舊版本bash曾經在那裡進行 globbing,並且1=foo在目前目錄中呼叫了一個文件時會做一些不同的事情)。
    • var+=*
  • 在關聯數組鍵中:

    • typeset -A hash; hash[**]=value; v=${hash[**]}. 雖然很特別*@
  • 在賦值後export// local///僅在某些情況下typeset:賦值關鍵字和變數名,declare即使是部分也不能被引用,也不能是任何擴展的結果。分配和重定向可能發生在之前,但不能使用。:readonly``=``command

    • 好的(沒有拆分+全域):

      • export a=*
      • x=1 < /dev/null export foo a=*
    • 不行(執行拆分+全域):

  • case * in (...); esac

  • case x in (*); esac(沒有 split+glob,但這*被視為一種模式,它也適用於在未引用的擴展中找到的萬用字元,如var=*; case x in ($var))。

  • 裡面[[...]]=但請注意,如果, ==,運算符右側存在未加引號的萬用字元,則會完成模式匹配!=

  • 從 4.4 版開始在這裡的字元串。在早期版本中,拆分(雖然不是萬用字元)已經完成,結果單詞用空格連接。

  • 在 shell 處於 POSIX 模式且非互動式時的重定向目標中:bash -o posix -c 'echo test > *. 否則,split+glob 將被執行,bash如果擴展為具有少於或多於 1 個元素的列表,則會報告錯誤。

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