什么是 Bash 中的列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52901012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 17:02:11  来源:igfitidea点击:

What is a list in Bash?

arraysbashlistshell

提问by Silv

I have searched for a similar question here, but surprisingly could not find any.

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

In GNU bash, there is (a construct? a structure? a data type?) called "arrays". Arrays are well documented in the bash documentation, so I think that I understand the basics.

在 GNU bash 中,有(一个构造?一个结构?一个数据类型?)称为“数组”。数组在 bash 文档中有详细记录,所以我认为我了解基础知识。

But suddenly, in the documentation there also comes up the term "list". For example, it is used when talking about filename expansion(emphasis is mine):

但突然间,在文档中也出现了“列表”一词。例如,在谈论文件名扩展时使用它(重点是我的):

If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted listof filenames matching the pattern (see Pattern Matching).

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

Therefore, I have three questions:

因此,我有三个问题:

  1. What does "list" mean here?
  2. Is it used in the same meaning as in for loop description?
  3. I am somehow lost in a whitespace world in bash. If this "list" is a separate concept to arrays (as I think), is it treated specially when it comes to whitespaces and IFS, or in the same way as an array?
  1. 这里的“列表”是什么意思?
  2. 它的使用含义与for 循环描述中的含义相同吗?
  3. 我不知何故迷失在 bash 的空白世界中。如果这个“列表”是一个独立于数组的概念(我认为),它是否在涉及空格和时被特殊对待IFS,或者以与数组相同的方式处理?

There is another use of the "list" termwhen talking about sequence of one or more pipelines, but I am aware that it most probably means a different kind of lists.

在谈论一个或多个管道的序列时,“列表”术语还有另一种用法,但我知道它很可能意味着不同类型的列表。



UPDATE

更新

  1. Since I see that the way that this "list structure" works is very similar to how arrays work – what are the differences between them?
  1. 由于我看到这种“列表结构”的工作方式与数组的工作方式非常相似——它们之间有什么区别?

UPDATE 2

更新 2

  1. What are the uses cases when "lists" are preferred over arrays? For example, let us compare. Let us create two files:

    $ touch file1.txt file2.txt

  1. 当“列表”比数组更受欢迎时有哪些用例?例如,让我们比较一下。让我们创建两个文件:

    $ touch file1.txt file2.txt

When it comes to lists, I can do the following:

当涉及到列表时,我可以执行以下操作:

$ A=*.txt ; echo $A
file1.txt file2.txt
$ 

And when it comes to arrays, I can do the following:

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

$ B=(*.txt) ; echo ${B[@]}
file1.txt file2.txt
$ 

While these two results are exactly the same, are there any cases when arrays and lists return different results?

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



UPDATE 3

更新 3

I might have confuse something, because in the above example it seems to be a list "wrapped" in an array. I do not know whether it makes a difference.

我可能混淆了一些东西,因为在上面的例子中,它似乎是一个“包装”在数组中的列表。我不知道这是否有所作为。

回答by codeforester

There is no data type called listin Bash. We just have arrays. In the documentation that you have quoted, the term "list" doesn't refer to a data type (or anything technical) - it just means a sequence of file names.

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

However, glob expansionswork very similar to array elements as far as sequential looping is considered:

但是,就考虑顺序循环而言,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

is same as

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

However, if you were to hardcode the file names, then you need quotes to prevent word splittingand globbing:

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

for file in verycramped.txt "quite spacious.txt" "too much space.txt" "*ry nights.txt"; do ...

or

或者

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


Read more about word splitting here:

在此处阅读有关分词的更多信息:

回答by Mark Reed

The term "list" is not really a specific technical term in bash; it is used in the grammar to refer to a sequence of commands (such as the body of a forloop, or the contents of a script), and this use has shown up in the documentation of program structure, but that's a very specific type of list.

术语“列表”在 bash 中并不是一个真正的技术术语;它在语法中用于指代一系列命令(例如for循环体或脚本的内容),这种用法已经出现在程序结构的文档中,但这是一种非常特殊的类型列表。

In the context you ask about, I'd say a "list" is a valuethat consists of any number (including 0) of shell words. The arguments to a single command are such a list.

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

A shell word, in turn, is what you might call a single string in another language. Normally, when you type a command line, it is separated into words by the characters listed in $IFS(normally whitespace, that is, spaces and horizontal tabs), but you can avoid that by any of the various quoting mechanisms and thus create shell words that contain IFS characters.

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

If you wish to storea list in a shell parameter, that parameter must be an array; in that case, each word of the list becomes an element of the array. For example, the list of arguments passed into a command are available in the default array, which is accessed via $followed by the index that would go in between the square brackets in a named array reference, e.g. "$@"for all the elements turned back into a list, "$0"for the first element (which is the command name), etc.

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

When an array is expanded back into a list of words, you have three options; the elements of the array can be kept as they originally were, irrespective of contents ("$@"); they can be concatenated together, joined by spaces, into one big single shell word ("$*"), or they can be first concatenated into one big string and then re-parsed into words using the usual IFS-delimiter rules ($@or $*without the quotation marks).

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

Except for a few builtins like mapfile(a.k.a. readarray), bash doesn't have much support for arrays. For example, the environment can only contain strings, so you can't exportan array. You can't pass an array into a function asan array, although you can certainly use the value of an array (or a slice of an array) as (some or all of) the list of arguments passed to a function. You can also pass the nameof an array to a function, which can then use name-references and evalto manipulate that array in its caller's scope, but as with all mechanisms for reaching out of one's lexical scope in any language, this is generally considered bad practice. And of course, a function can't return an array, but then a bash function can't returnanything but a one-byte numeric exit code. It can outputtext, but that text is unstructured; if the caller captures it with command or process substitution, it's up to that caller to parse the text however it desires – such as making an array containing one element word for each line of output, which is the default behavior of mapfile/readarray.

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

Anyway, the point is, lists in this context are values, while arrays are containers that store list values. Technically, shell parameters (a.k.a. "variables") can be arrays, and as arrays they can holdlists; they can't belists, and it doesn't really make sense to refer to an "array value". But informally, "array" and "list" are often used interchangeably; that's the nature of lazy humans and the shell's fluidity.

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

回答by David C. Rankin

A list in bash is a specific sequence of expressions separated by a pipeline. From man bash, e.g.

bash 中的列表是由管道分隔的特定表达式序列。从man bash,例如

Lists

   A list is a sequence of one or more pipelines separated by one of the 
   operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or 
   <newline>. 

   Of these list operators, && and || have equal precedence, followed by 
   ; and &, which have equal precedence.

   A sequence of one or more newlines may appear in a list instead of a 
   semicolon to delimit commands.

   If a command is terminated by the control operator &, the shell 
   executes the command in the background in a subshell. The shell does 
   not wait for the command to finish, and the return status is 0. 
   Commands separated by a ; are executed sequentially; the shell waits 
   for each command to terminate in turn. The return status is the exit 
   status of the last command executed.

   AND and OR lists are sequences of one of more pipelines separated by 
   the && and || control operators, respectively. AND and OR lists are 
   executed with left associativity. An AND list has the form

          command1 && command2

   command2 is executed if, and only if, command1 returns an exit status 
   of zero.

   An OR list has the form

          command1 || command2

   command2 is executed if and only if command1 returns a non-zero exit 
   status. The return status of AND and OR lists is the exit status of 
   the last command executed in the list.
Lists

   A list is a sequence of one or more pipelines separated by one of the 
   operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or 
   <newline>. 

   Of these list operators, && and || have equal precedence, followed by 
   ; and &, which have equal precedence.

   A sequence of one or more newlines may appear in a list instead of a 
   semicolon to delimit commands.

   If a command is terminated by the control operator &, the shell 
   executes the command in the background in a subshell. The shell does 
   not wait for the command to finish, and the return status is 0. 
   Commands separated by a ; are executed sequentially; the shell waits 
   for each command to terminate in turn. The return status is the exit 
   status of the last command executed.

   AND and OR lists are sequences of one of more pipelines separated by 
   the && and || control operators, respectively. AND and OR lists are 
   executed with left associativity. An AND list has the form

          command1 && command2

   command2 is executed if, and only if, command1 returns an exit status 
   of zero.

   An OR list has the form

          command1 || command2

   command2 is executed if and only if command1 returns a non-zero exit 
   status. The return status of AND and OR lists is the exit status of 
   the last command executed in the list.

A Listis used in forming Compound Commands(see man bash).

AList用于成型Compound Commands(参见man bash)。

There is another use of the "list" term when talking about sequence of one or more pipelines, but I am aware that it most probably means a different kind of lists.

在谈论一个或多个管道的序列时,“列表”术语还有另一种用法,但我知道它很可能意味着不同类型的列表。

Both:

两个都:

$ A=*.txt ; echo $A

and

$ B=(*.txt) ; echo ${B[@]}

technically are Listsin bash.

从技术上讲是Lists在 bash 中。