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.
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 list of filenames matching the pattern (see Pattern Matching).
Therefore, I have three questions:
IFS
, or in the same way as an array?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.
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
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?
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.
Bash Array – An array is a collection of elements. Unlike in many other programming languages, in bash, an array is not a collection of similar elements. Since bash does not discriminate string from a number, an array can contain a mix of strings and numbers.
We can use regular expressions in Bash using [[ STRING =~ REGEX ]]. This command returns the value 0 if the regular expression matches. Otherwise, it returns the value 1. As we need this behavior in the exist_in_list function, we can run the [[ ]] command without any explicit return command.
What Is List And Arrays In Bash There is no data structure in array with name List. But List is generally refer to the "list of items" in Bash Loops. Let us look at an example.
Bash is a command processor that typically runs in a text window where the user types commands that cause actions. Bash can also read and execute commands from a file, called a shell script. Like all Unix shells, it supports filename globbing (wildcard matching), piping, here documents, command substitution, variables, ...
There are a set of characters the Bash shell treats in two different ways. When you type them at the shell, they act as instructions or commands and tell the shell to perform a certain function. Think of them as single-character commands. Sometimes, you just want to print a character and don’t need it to act as a magic symbol.
How to check if a Bash Array contains a value? There is no in array operator in bash to check if an array contains a value. Instead, to check if a bash array contains a value you will need to test the values in the array by using a bash conditional expression with the binary operator =~.
There is no data type called list in 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.
However, glob expansions work very similar to array elements as far as sequential looping is considered:
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 splitting and 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:
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 for
loop, 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.
In the context you ask about, I'd say a "list" is a value that consists of any number (including 0) of shell words. The arguments to a single command are such a list.
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.
If you wish to store a 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.
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).
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 export
an array. You can't pass an array into a function as an 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 name of an array to a function, which can then use name-references and eval
to 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 return anything but a one-byte numeric exit code. It can output text, 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
.
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 hold lists; they can't be lists, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With