Bash

bash數組表現得很奇怪

  • October 19, 2021

我在 /tmp 下有兩個文件夾。

從終端:

ls -d /tmp/firefox-*

/tmp/firefox-sy2vakcj.default-esr-charlie-cache
/tmp/firefox-sy2vakcj.default-esr-charlie-profile

或者

compgen -G /tmp/firefox-*

/tmp/firefox-sy2vakcj.default-esr-charlie-cache
/tmp/firefox-sy2vakcj.default-esr-charlie-profile

我也可以將輸出儲存在一個數組中:

arr=( $(ls -d /tmp/firefox-*) )
echo $arr
tmp/firefox-sy2vakcj.default-esr-charlie-cache  /tmp/firefox-sy2vakcj.default-esr-charlie-profile

echo $arr[1] 
tmp/firefox-sy2vakcj.default-esr-charlie-cache

echo $arr[2]
/tmp/firefox-sy2vakcj.default-esr-charlie-profile

到目前為止,一切都很好。

但是如果我從腳本中嘗試同樣的事情:

   ...
   ... 
   arr=( "$(ls -d /tmp/firefox-*)" ) ||( echo "directory doesn't exist" && exit 1)
   #arr=( "$(compgen -G /tmp/firefox-*)" ) ||( echo "directory doesn't exist" && exit 1)
   echo "this is a test for arr[1]: $arr[1]"
   echo "this is a test for arr[2]: $arr[2]"
   ...

我得到輸出:

從腳本:

這是ls -d輸出:

+ arr=("$(ls -d /tmp/firefox-*)")
++ ls -d '/tmp/firefox-*'
ls: cannot access '/tmp/firefox-*': No such file or directory
+ echo 'directory doesn'\''t exist'
directory doesn't exist

對於compgen -G,這是輸出:

this is a test for arr[1]: /tmp/firefox-sy2vakcj.default-esr-charlie-cache
/tmp/firefox-sy2vakcj.default-esr-charlie-profile[1]
this is a test for arr[2]: /tmp/firefox-sy2vakcj.default-esr-charlie-cache
/tmp/firefox-sy2vakcj.default-esr-charlie-profile[2]

我的問題:

**1.**為什麼 glob 沒有在命令的 subshel​​l 中擴展 ls -d

**2.**使用compgen -G,數組中的值是如何儲存的?輸出似乎數組中的每個條目都儲存目錄條目和第二個具有自己的索引數組的條目?

**3.**兩個命令的終端輸出是否與腳本不同,還是我遺漏了什麼?

  1. 為什麼命令 ls -d 的 glob 沒有在子 shell 中擴展?

您可能已經使用set -f. 展示:

$ touch firefox-1 firefox-2
$ arr=( firefox-* ); declare -p arr
declare -a arr=([0]="firefox-1" [1]="firefox-2")
$ set -f
$ arr=( firefox-* ); declare -p arr
declare -a arr=([0]="firefox-*")
  1. 使用 compgen -G,值如何儲存在數組中?輸出似乎數組中的每個條目都儲存目錄條目和第二個具有自己的索引數組的條目?

當您這樣做arr=( "$(compgen -G /tmp/firefox-*)" )時,雙引號會強制將 compgen 輸出儲存為數組中的單個元素。在這種情況下,要將輸出行讀入數組,請mapfile與程序替換一起使用:

$ mapfile -t arr < <(compgen -G ./firefox-*)
$ declare -p arr
declare -a arr=([0]="./firefox-1" [1]="./firefox-2")
  1. 兩個命令的終端輸出是否與腳本不同,還是我遺漏了什麼?

看起來您的互動式 shell 是 zsh。除此之外,您缺少需要大括號(3.5.3 Shell Parameter Expansion)的數組元素的參數擴展語法,並且 bash 數組從零開始索引:

echo "${arr[0]}"

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