I fail to understand what is happening between these two array creation, tested on cygwin GNU bash
我无法理解在cygwin GNU bash上测试的这两个数组创建之间发生了什么
$ array=('hello world' how are you)
$ echo $array
'hello world' <----- This is expected
EDIT : As chepner pointed it out the output is
编辑:切普纳指出输出是
hello world <----- no ''
Now with variable assignment as an intermediate step
变量赋值作为中间步骤
$ words="'hello world' how are you"
$ echo $words
'hello world' how are you
$ array=($words)
$ echo $array
'hello <----- Why was it split with ' '?
5 个解决方案
#1
2
codeforester's helpful answer explains the issue well.
codeforester这个有用的回答很好地解释了这个问题。
As for a solution:
作为一个解决方案:
Note: If the input you're dealing with doesn't actually have embedded quoting to demarcate elements, simply use readarray -t array < <(...)
as is, where (...
) represents the output-producing command whose lines should be captured as the individual elements of an array.
注意:如果您正在处理的输入实际上没有嵌入的引号来划分元素,那么只需使用readarray -t数组< <(…),其中(…)表示输出生成命令,其行应该作为数组的单个元素来捕获。
xargs
generally understands shell quoting in literal input (except for escaped, embedded quotes):
xargs通常理解文本输入中的shell引用(除了转义外,嵌入引号):
words="'hello world' how are you"
echo "$words" | xargs -n 1 printf '%s\n'
hello world
how
are
you
Note how hello world
was recognized as a single argument, and how its enclosing '
instances were removed.
请注意hello world是如何被认为是一个单一的参数,以及它的封闭实例是如何被删除的。
To utilize this when creating an array in bash
(assumes Bash 4.x due to readarray
, but it's possible to make it work in Bash 3.x[1] ):
在bash中创建数组时使用此方法(假设bash 4)。由于readarray,所以可以在Bash 3中工作。x[1]):
words="'hello world' how are you"
readarray -t array < <(xargs -n 1 printf '%s\n' <<<"$words")
declare -p array
which yields:
收益率:
declare -a array=([0]="hello world" [1]="how" [2]="are" [3]="you")
(The enclosing "
instances are an artifact of the declare -p
output format - they have syntactic function, if you were to reuse the output as shell source code.)
(附带的“实例是声明-p输出格式的产物——如果您要将输出作为shell源代码重用,它们具有语法功能)。
[1] A Bash v3+ solution, using read
instead of readarray
:words="'hello world' how are you" IFS=$'\n' read -d '' -ra array < <(xargs -n 1 printf '%s\n' <<<"$words") declare -p array
[1]一个Bash v3+解决方案,使用read而不是readarray: words="'hello world' how are you" IFS= '\n' read -d " -ra array <(xargs -n 1 printf ' s %s\n' s ' s ' <"$words")声明-p数组
#2
2
From Bash manual:
从Bash手册:
Referencing an array variable without a subscript is equivalent to referencing with a subscript of 0.
When you put single quotes inside double quotes as in:
当你把单引号放在双引号中,如:
words="'hello world' how are you"
the single quotes become a literal part of the string and hence won't prevent word split when you initialize the array with
单引号成为字符串的文字部分,因此在初始化数组时不会阻止单词split。
array=($words)
wherein 0th element of the array would become 'hello
. To prevent word splitting in this case, do this:
其中,数组的第0个元素将变为“hello”。为了避免在这种情况下出现分词,请这样做:
array=("$words")
However, that wouldn't achieve your intention of making hello world
as the 0th element. The direct assignment array=('hello world' how are you)
is the right way of doing it.
然而,这并不能实现您将hello world作为第0个元素的意图。直接赋值数组=('hello world' how are you)是正确的方法。
See also:
参见:
- Difference between single and double quotes in Bash
- Bash中的单引号和双引号之间的差异
- Word splitting
- 分词
#3
0
It's the dereferencing. Try this:
非关联化。试试这个:
$ array=('hello world' how are you)
$ echo $array
hello world
$ echo ${array[@]}
hello world how are you
$ echo ${array[0]}
hello world
$ echo ${array[1]}
how
$ echo ${array[2]}
are
$ echo ${array[3]}
you
#4
0
"Referring to the content of a member variable of an array without providing an index number is the same as referring to the content of the first element, the one referenced with index number zero." From this page, last line of section 10.2.2
“在不提供索引号的情况下,引用一个数组的成员变量的内容与引用第一个元素的内容是一样的,这个元素引用索引号为0。”在本页,第10.2.2节的最后一行
So
所以
$ echo $array
is equivalent to
相当于
$ echo ${array[0]}
#5
0
In the first case single quotes prevent word splitting to split hello world in two arguments, the single quotes are not echoed
在第一种情况下,单引号防止在两个参数中拆分hello world,单引号不会被重复
$ array=('hello world' how are you)
$ echo $array
hello world
in the second, the quotes are string literal, arguments are split, this can't be seen because echo displays all arguments, if you use printf "<%s>\n" $words
you will see better
第二,引号是字符串文字,参数是拆分的,因为echo显示所有参数,如果您使用printf“<%s>\n”$words,您将会看到更好的结果
$ words="'hello world' how are you"
$ echo $words
'hello world' how are you
$ array=($words)
$ echo $array
'hello
$ words="'hello world' how are you"
$ printf "<%s>\n" $words
<'hello>
<world'>
<how>
<are>
<you>
As said in comments, eval is dangerous, you must know what you are doing
正如评论所说,eval是危险的,你必须知道你在做什么
$ eval "array=($words)"
$ printf "<%s>\n" "${array[@]}"
<hello world>
<how>
<are>
<you>
#1
2
codeforester's helpful answer explains the issue well.
codeforester这个有用的回答很好地解释了这个问题。
As for a solution:
作为一个解决方案:
Note: If the input you're dealing with doesn't actually have embedded quoting to demarcate elements, simply use readarray -t array < <(...)
as is, where (...
) represents the output-producing command whose lines should be captured as the individual elements of an array.
注意:如果您正在处理的输入实际上没有嵌入的引号来划分元素,那么只需使用readarray -t数组< <(…),其中(…)表示输出生成命令,其行应该作为数组的单个元素来捕获。
xargs
generally understands shell quoting in literal input (except for escaped, embedded quotes):
xargs通常理解文本输入中的shell引用(除了转义外,嵌入引号):
words="'hello world' how are you"
echo "$words" | xargs -n 1 printf '%s\n'
hello world
how
are
you
Note how hello world
was recognized as a single argument, and how its enclosing '
instances were removed.
请注意hello world是如何被认为是一个单一的参数,以及它的封闭实例是如何被删除的。
To utilize this when creating an array in bash
(assumes Bash 4.x due to readarray
, but it's possible to make it work in Bash 3.x[1] ):
在bash中创建数组时使用此方法(假设bash 4)。由于readarray,所以可以在Bash 3中工作。x[1]):
words="'hello world' how are you"
readarray -t array < <(xargs -n 1 printf '%s\n' <<<"$words")
declare -p array
which yields:
收益率:
declare -a array=([0]="hello world" [1]="how" [2]="are" [3]="you")
(The enclosing "
instances are an artifact of the declare -p
output format - they have syntactic function, if you were to reuse the output as shell source code.)
(附带的“实例是声明-p输出格式的产物——如果您要将输出作为shell源代码重用,它们具有语法功能)。
[1] A Bash v3+ solution, using read
instead of readarray
:words="'hello world' how are you" IFS=$'\n' read -d '' -ra array < <(xargs -n 1 printf '%s\n' <<<"$words") declare -p array
[1]一个Bash v3+解决方案,使用read而不是readarray: words="'hello world' how are you" IFS= '\n' read -d " -ra array <(xargs -n 1 printf ' s %s\n' s ' s ' <"$words")声明-p数组
#2
2
From Bash manual:
从Bash手册:
Referencing an array variable without a subscript is equivalent to referencing with a subscript of 0.
When you put single quotes inside double quotes as in:
当你把单引号放在双引号中,如:
words="'hello world' how are you"
the single quotes become a literal part of the string and hence won't prevent word split when you initialize the array with
单引号成为字符串的文字部分,因此在初始化数组时不会阻止单词split。
array=($words)
wherein 0th element of the array would become 'hello
. To prevent word splitting in this case, do this:
其中,数组的第0个元素将变为“hello”。为了避免在这种情况下出现分词,请这样做:
array=("$words")
However, that wouldn't achieve your intention of making hello world
as the 0th element. The direct assignment array=('hello world' how are you)
is the right way of doing it.
然而,这并不能实现您将hello world作为第0个元素的意图。直接赋值数组=('hello world' how are you)是正确的方法。
See also:
参见:
- Difference between single and double quotes in Bash
- Bash中的单引号和双引号之间的差异
- Word splitting
- 分词
#3
0
It's the dereferencing. Try this:
非关联化。试试这个:
$ array=('hello world' how are you)
$ echo $array
hello world
$ echo ${array[@]}
hello world how are you
$ echo ${array[0]}
hello world
$ echo ${array[1]}
how
$ echo ${array[2]}
are
$ echo ${array[3]}
you
#4
0
"Referring to the content of a member variable of an array without providing an index number is the same as referring to the content of the first element, the one referenced with index number zero." From this page, last line of section 10.2.2
“在不提供索引号的情况下,引用一个数组的成员变量的内容与引用第一个元素的内容是一样的,这个元素引用索引号为0。”在本页,第10.2.2节的最后一行
So
所以
$ echo $array
is equivalent to
相当于
$ echo ${array[0]}
#5
0
In the first case single quotes prevent word splitting to split hello world in two arguments, the single quotes are not echoed
在第一种情况下,单引号防止在两个参数中拆分hello world,单引号不会被重复
$ array=('hello world' how are you)
$ echo $array
hello world
in the second, the quotes are string literal, arguments are split, this can't be seen because echo displays all arguments, if you use printf "<%s>\n" $words
you will see better
第二,引号是字符串文字,参数是拆分的,因为echo显示所有参数,如果您使用printf“<%s>\n”$words,您将会看到更好的结果
$ words="'hello world' how are you"
$ echo $words
'hello world' how are you
$ array=($words)
$ echo $array
'hello
$ words="'hello world' how are you"
$ printf "<%s>\n" $words
<'hello>
<world'>
<how>
<are>
<you>
As said in comments, eval is dangerous, you must know what you are doing
正如评论所说,eval是危险的,你必须知道你在做什么
$ eval "array=($words)"
$ printf "<%s>\n" "${array[@]}"
<hello world>
<how>
<are>
<you>