bash 数组表现得很奇怪

bash 数组表现得很奇怪

我在 /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 没有在命令的子 shell 中展开 ls -d

2.对于compgen -G,值如何存储在数组中?输出似乎数组中的每个条目都存储目录条目和第二个目录条目及其自己的索引数组?

3.这两个命令的终端输出是否与脚本不同,或者我遗漏了什么?

答案1

  1. 为什么 glob 没有在命令 ls -d 的子 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参数扩展),并且 bash 数组是从零开始索引的:

echo "${arr[0]}"

相关内容