简体   繁体   English

创建一个包含空格的元素的 Bash 数组

[英]Creating a Bash array with elements that have whitespaces in them

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 ' '? 

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 array < <(...)作为是,其中( ... )为输出生产指令,其应该被捕获为数组的单个元素

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.x 由于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 .) (封闭的"实例是declare -p输出格式的declare -p ——它们具有句法功能,如果您要将输出重用为shell源代码。)


[1] A Bash v3+ solution, using read instead of readarray : [1] Bash v3+ 解决方案,使用read而不是readarray
words="'hello world' how are you" IFS=$'\\n' read -d '' -ra array < <(xargs -n 1 printf '%s\\n' <<<"$words") declare -p array

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单引号成为字符串的文字部分,因此在初始化数组时不会阻止单词拆分

array=($words)

wherein 0th element of the array would become 'hello .其中数组的第 0 个元素将变为'hello To prevent word splitting in this case, do this:为了防止在这种情况下分词,请执行以下操作:

array=("$words")

However, that wouldn't achieve your intention of making hello world as the 0th element.但是,这不会实现您将hello world作为第 0 个元素的意图。 The direct assignment array=('hello world' how are you) is the right way of doing it.直接赋值array=('hello world' how are you)是正确的方法。


See also:另见:

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

"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这个页面,第 10.2.2 节的最后一行

So所以

$ echo $array

is equivalent to相当于

$ echo ${array[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>

What about something like怎么样的东西

$ array=($(echo -e $'a a\nb b' | tr ' ' '§')) && array=("${array[@]//§/ }") && echo "${array[@]/%/ INTERELEMENT}"

a a INTERELEMENT b b INTERELEMENT

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM