bash 循环遍历带空格的字符串数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12300599/
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 03:13:17  来源:igfitidea点击:

Loop through array of arrays of string with spaces

linuxarraysbashshellfor-loop

提问by A K

I'm trying to loop through an array that contains other arrays and these arrays consist of strings with spaces. The problem is that I can't seem to preserve the spacing in the string. The string with spaces are either divided into multiple items if I change IFS to \n or all the elements of the array are seen as 1 item if I leave IFS unchanged here's some sample code:

我试图遍历一个包含其他数组的数组,这些数组由带空格的字符串组成。问题是我似乎无法保留字符串中的间距。如果我将 IFS 更改为 \n,则带空格的字符串要么被分成多个项目,要么如果我保持 IFS 不变,则数组的所有元素都被视为 1 个项目,这里有一些示例代码:

#!/bin/sh
low1=("AA  QQ" "BB  LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)

for high_item in ${high[@]}
do
   eval arrayz=${$high_item[@]}
   #IFS=$'\n'
   for item in $arrayz
   do
      echo $item
   done
done

Output:

输出:

AA
QQ
BB
LL
CC
DD
EE
FF

As you can see the elements "AA QQ" and "BB LL" have been split.

如您所见,元素“AA QQ”和“BB LL”已被拆分。

If I uncomment the line that sets IFSto \nI get the following:

如果我取消注释设置IFS为的行,\n我会得到以下信息:

AA QQ BB LL
CC DD
EE FF

Now "AA QQ" and "BB LL" are concatenated!

现在“AA QQ”和“BB LL”连接起来了!

Is there anyway I can preserve these elements just as they original are...I need the output to look like that:

无论如何我可以保留这些元素,就像它们原来的一样......我需要输出看起来像这样:

AA QQ
BB LL
CC 
DD
EE 
FF

回答by Micha? Górny

I think you meant that the output should look like:

我认为你的意思是输出应该是这样的:

AA  QQ
BB  LL
CC
DD
EE
FF

i.e.:

IE:

${low1[0]}
${low1[1]}
${low2[0]}
${low2[1]}
${low3[0]}
${low3[1]}

This could be accomplished using:

这可以使用以下方法完成:

#!/bin/bash

low1=("AA  QQ" "BB  LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)

for high_item in ${high[@]}
do
    x="${high_item}[@]" # -> "low1[@]"
    arrays=( "${!x}" )

    #IFS=$'\n'
    for item in "${arrays[@]}"
    do
        echo "$item"
    done
done

And pleasealways use #!/bin/bashfor bash scripts.

并且始终#!/bin/bash用于 bash 脚本。

Explanation: ${!x}is indirect variable expansion. It evaluates to the value of variable with a name contained in $x.

解释:${!x}是间接变量展开。它的计算结果是名称包含在 中的变量的值$x

For our needs, xneeds to have the [@]suffix for array expansion as well. Especially note that it is x=${high_item}[@]and notx=${high_item[@]}.

对于我们的需要,还x需要有[@]数组扩展的后缀。特别注意它是x=${high_item}[@]不是x=${high_item[@]}

And you have toevaluate it in array context; otherwise, it wouldn't work as expected (if you do arrays=${!x}).

必须在数组上下文中评估它;否则,它不会按预期工作(如果你这样做arrays=${!x})。

Ah, and as final note: IFSdoesn't make any difference here. As long as you are working on quoted arrays, IFSdoesn't come into play.

啊,最后一点:IFS这里没有任何区别。只要您正在处理引用数组,IFS就不会起作用。

回答by chepner

Replace evalwith indirect parameter expansion, and you'll get what I think you want (although it doesn't match your current given output:

替换eval为间接参数扩展,您将得到我认为您想要的(尽管它与您当前的给定输出不匹配:

for high_item in "${high[@]}"
do
    arrayz="$high_item[@]"
    # arrayz is just a string like "low1[@]"
    for item in "${!arrayz}"
    do
        echo $item
    done
done

Note the need to quote the array expansion in the inner loop to preserve the whitespace in elements of low1.

请注意需要在内循环中引用数组扩展以保留low1.