什么是bash中的列表?

Sil*_*ilv 6 arrays bash shell list

我在这里搜索过类似的问题,但令人惊讶的是找不到任何问题.

在GNU bash中,有一个名为" arrays "的(一个构造?一个结构?一个数据类型?).数组在bash文档中有详细记录,所以我认为我理解了基础知识.

但突然间,在文档中也出现了"列表"一词.例如,在讨论文件名扩展时使用它(强调是我的):

如果出现其中一个字符,则该单词被视为模式,并替换为与该模式匹配的按字母顺序排列的文件名列表(请参阅模式匹配).

因此,我有三个问题:

  1. "列表"在这里意味着什么?
  2. 它是否与for循环描述中的含义相同?
  3. 我在某种程度上迷失在bash的空白世界中.如果这个"列表"是一个单独的数组概念(正如我所想的那样),它是否在涉及空格时特别对待IFS,或者与数组相同?

还有另一种使用"名单"一词在谈论一个或多个管道的序列时,但我知道,很可能意味着不同类型的列表.


UPDATE

  1. 因为我看到这个"列表结构"的工作方式与数组的工作方式非常相似 - 它们之间有什么区别?

更新2

  1. 当"列表"优于数组时,有哪些用例?例如,让我们进行比较.让我们创建两个文件:

    $ touch file1.txt file2.txt

说到列表,我可以执行以下操作:

$ A=*.txt ; echo $A
file1.txt file2.txt
$ 
Run Code Online (Sandbox Code Playgroud)

当涉及到数组时,我可以执行以下操作:

$ B=(*.txt) ; echo ${B[@]}
file1.txt file2.txt
$ 
Run Code Online (Sandbox Code Playgroud)

虽然这两个结果完全相同,但是当数组和列表返回不同的结果时是否存在任何情况?


更新3

我可能会混淆一些东西,因为在上面的例子中,它似乎是一个"包裹"在数组中的列表.我不知道它是否有所作为.

cod*_*ter 7

Bash中没有名为list的数据类型.我们只有数组.在您引用的文档中,术语"列表"不是指数据类型(或任何技术) - 它只是指一系列文件名.

但是,就所考虑的顺序循环而言,glob扩展的工作方式与数组元素非常相似:

for file in *.txt; do          # loop through the matching files
                               # no need to worry about white spaces or glob characters in file names
  echo "file=$file"
done
Run Code Online (Sandbox Code Playgroud)

和...一样

files=(*.txt)                  # put the list of matching files in an array
for file in "${files[@]}"; do  # loop through the array
  echo "file=$file"
done
Run Code Online (Sandbox Code Playgroud)

但是,如果您要对文件名进行硬编码,那么您需要使用引号来防止分和通配:

for file in verycramped.txt "quite spacious.txt" "too much space.txt" "*ry nights.txt"; do ...
Run Code Online (Sandbox Code Playgroud)

要么

files=(verycramped.txt "quite spacious.txt" "too much space.txt" "*ry nights.txt")
for file in "${files[@]}"; do ...
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多关于分词的内容:

  • 换句话说,它只是在英语意义上用于表示一系列项目,而不是任何技术意义上的. (4认同)

Mar*_*eed 6

术语“列表”实际上并不是 bash 中的特定技术术语;它是 bash 中的一个术语。它在语法中用于指代命令序列(例如循环体for或脚本的内容),并且这种用法已显示在程序结构的文档中,但这是非常具体的列表类型。

\n\n

在您询问的上下文中,我会说“列表”是由任意数量(包括 0)的 shell单词组成的。单个命令的参数就是这样一个列表。

\n\n

反过来,shell 词可能是另一种语言中的单个字符串。通常,当您键入命令行时,它会被列出的字符$IFS(通常是空格,即空格和水平制表符)分隔成单词,但是您可以通过任何各种引用机制来避免这种情况,从而创建 shell 单词包含 IFS 字符。

\n\n

如果您希望在 shell 参数中存储列表,则该参数必须是数组;在这种情况下,列表中的每个单词都会成为数组的一个元素。例如,传递到命令的参数列表在默认数组中可用,可以通过$后跟命名数组引用中方括号之间的索引来访问该数组,例如,"$@"对于返回到列表中的所有元素,"$0"对于第一个元素(即命令名称),等等。

\n\n

当数组扩展回单词列表时,您有三个选择:数组的元素可以保持原样,而不管内容如何 ( "$@");它们可以通过空格连接在一起,形成一个大的单 shell 单词 ( ),或者可以首先将它们连接成一个大字符串,然后使用通常的 IFS 分隔符规则(或不使用引号)"$*"重新解析为单词。$@$*

\n\n

除了一些内置函数mapfile(例如readarray)之外,bash 对数组没有太多支持。例如,环境只能包含字符串,因此不能包含export数组。尽管您当然可以使用数组(或数组切片)的值作为传递给函数的参数列表(部分或全部),但您不能将数组作为数组传递到函数。您还可以将数组的名称传递给函数,然后该函数可以使用名称引用并eval在其调用者的范围内操作该数组,但与在任何情况下超出一个人的词法范围的所有机制一样语言,这通常被认为是不好的做法。当然,函数不能返回数组,但是 bash 函数除了一字节数字退出代码之外不能返回任何内容。它可以输出文本,但该文本是非结构化的;如果调用者通过命令或进程替换捕获它,则由调用者来解析文本,但是它需要 \xe2\x80\x93 ,例如为每一行输出创建一个包含一个元素单词的数组,即mapfile/的默认行为readarray

\n\n

无论如何,重点是,在此上下文中的列表是值,而数组是存储列表值的容器。从技术上讲,shell 参数(又名“变量”)可以是数组,并且作为数组,它们可以保存列表;它们不能列表,并且引用“数组值”并没有真正的意义。但在非正式场合,“数组”和“列表”经常互换使用。这就是人类懒惰的本质和外壳的流动性。

\n