如果数组来自源文件,则在 bash 中按索引访问数组将无法正常工作

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

Accessing Array by index in bash doesn't work correctly if array is from a sourced file

arraysbashindexing

提问by Rebecca Meritz

In bash when I access an array by index I get strange behavior if the array is a variable that was imported in the source of another bash script. What causes this behavior? How can it be fixed so an array that is sourced from another bash script behaves the same way as an array defined from within the running script?

在 bash 中,当我按索引访问数组时,如果数组是在另一个 bash 脚本的源中导入的变量,我会得到奇怪的行为。是什么导致了这种行为?如何修复它以使源自另一个 bash 脚本的数组的行为与从运行脚本中定义的数组的行为相同?

${numbers[0]} evals to "one two three" and not "one" as it should.The full test I've tried to demonstrate this behavior is shown below:

${numbers[0]} evals 为“一二三”而不是它应该的“一”。我试图证明这种行为的完整测试如下所示:

Source of test.sh :

test.sh 的来源:

#!/bin/bash

function test {

    echo "Length of array:"
    echo ${#numbers[@]}

    echo "Directly accessing array by index:"
    echo ${numbers[0]}
    echo ${numbers[1]}
    echo ${numbers[2]}

    echo "Accessing array by for in loop:"
    for number in ${numbers[@]}
    do
        echo $number
    done

    echo "Accessing array by for loop with counter:"
    for (( i = 0 ; i < ${#numbers[@]} ; i=$i+1 ));
    do
        echo $i
        echo ${numbers[${i}]}
    done
}

numbers=(one two three)
echo "Start test with array from within file:"
test 

source numbers.sh
numbers=${sourced_numbers[@]}
echo -e "\nStart test with array from source file:"
test

Source of number.sh :

number.sh 的来源:

#!/bin/bash
#Numbers

sourced_numbers=(one two three)

Output of test.sh :

test.sh 的输出:

Start test with array from within file:
Length of array:
3
Directly accessing array by index:
one
two
three
Accessing array by for in loop:
one
two
three
Accessing array by for loop with counter:
0
one
1
two
2
three

Start test with array from source file:
Length of array:
3
Directly accessing array by index:
one two three
two
three
Accessing array by for in loop:
one
two
three
two
three
Accessing array by for loop with counter:
0
one two three
1
two
2
three

回答by Gordon Davisson

The problem has nothing to do with sourcing; it's happening because the assignment numbers=${sourced_numbers[@]}doesn't do what you think it does. It converts the array (sourced_numbers) into a simple string, and stores that in the first element of numbers(leaving "two" "three" in the next two elements). To copy it as an array, use numbers=("${sourced_numbers[@]}")instead.

这个问题与采购无关;它的发生是因为任务numbers=${sourced_numbers[@]}没有按照你的想法去做。它将数组 ( sourced_numbers) 转换为一个简单的字符串,并将其存储在的第一个元素中numbers(在接下来的两个元素中留下“二”“三”)。要将其复制为数组,请numbers=("${sourced_numbers[@]}")改用。

BTW, for number in ${numbers[@]}is the wrong way to loop through an array's elements, because it'll break on whitespace in the elements (in this case, the array contains "one two three" "two" "three", but the loop runs for "one", "two", "three", "two", "three"). Use for number in "${numbers[@]}"instead. Actually, it's good to get in the habit of double-quoting pretty much all variable substitutions (e.g. echo "${numbers[${i}]}"), as this is not the only place where leaving them unquoted could cause trouble.

顺便说一句,for number in ${numbers[@]}循环遍历数组的元素是错误的方法,因为它会在元素中的空格处中断(在这种情况下,数组包含“一二三”“二”“三”,但循环运行“一”、“二”、“三”、“二”、“三”)。使用for number in "${numbers[@]}"来代替。实际上,养成双引号几乎所有变量替换(例如echo "${numbers[${i}]}")的习惯是很好的,因为这不是将它们不加引号会导致麻烦的唯一地方。