Bash从外部文件读取数组

时间:2011-01-13 21:12:52

标签: bash

我已经设置了一个Bash菜单脚本,该脚本也需要用户输入。 这些输入被写入(附加)一个名为var.txt的文本文件,如下所示:

input[0]='192.0.0.1'
input[1]='username'
input[2]='example.com'
input[3]='/home/newuser' 

现在我想要完成的是能够从类似这样的脚本中读取var.txt:

useradd var.txt/${input[1]}

现在我知道仅仅使用它作为一个例子。

先谢谢, 乔

3 个答案:

答案 0 :(得分:14)

使用bash's readarray statement。 (这是我可以找到动态地在数组元素中放置空格的唯一方法。)你需要你的var.txt文件只包含数组的元素,每行一个,不包含赋值语句。

readarray -t input < var.txt

有关详细信息,请尝试help readarray(然后会告诉您尝试help mapfile)。

这是我对它的测试:

echo -e "a\nb c\nd" > var.txt
readarray input < var.txt 
for item in "${input[@]}"; do echo $item; done

打印:

a
b c
d

注意:执行cat var.txt | readarray -t input不起作用。我认为这是因为input变量的范围超出了范围。

答案 1 :(得分:6)

如果整个var.txt文件只包含您指定的与Bash兼容的变量赋值,您可能只能source,以便在新的Bash脚本中使这些变量可用:

source var.txt

useradd ${input[1]}

但是,这将覆盖任何具有相同名称的现有变量。通过选择特定变量,可以使用Command substitution来避免这种情况:

input[1]="$(grep '^input\[1\]=' var.txt | sed "s|[^=]*='\(.*\)'|\1|")"

它允许重命名变量,但您必须为每个感兴趣的变量执行此操作。它本质上从var.txt文件中提取变量的值,并将其分配给新变量。有关其使用的详细信息,请参阅grep manual pagesed info page

Process substitution可能允许更简单的表达式:

source <(grep '^input\[[0-9]*\]=' var.txt)

useradd ${input[1]}

这将允许您仅导入感兴趣的定义,但您必须注意不需要的变量覆盖。

答案 2 :(得分:3)

您可以将变量提取封装在函数中,并利用declare在函数内部使用时创建局部变量的事实。每次调用函数时,此技术都会读取文件。

readvar () {
    # call like this: readvar filename variable
    while read -r line
    do
        # you could do some validation here
        declare "$line"
    done < "$1"
    echo ${!2}
}

给定一个名为“data”的文件,其中包含:

input[0]='192.0.0.1'
input[1]='username'
input[2]='example.com'
input[3]='/home/newuser'
foo=bar
bar=baz

你可以这样做:

$ a=$(readvar data input[1])
$ echo "$a"
username
$ readvar data foo
bar

这将读取一个数组并重命名:

readarray () {
    # call like this: readarray filename arrayname newname
    # newname may be omitted and will default to the existing name
    while read -r line
    do
        declare "$line"
    done < "$1"
    local d=$(declare -p $2)
    echo ${d/#declare -a $2/declare -a ${3:-$2}};
}

示例:

$ eval $(readarray data input output)
$ echo ${output[2]}
example.com
$ echo ${output[0]}
192.0.0.1
$ eval $(readarray data input)
$ echo ${input[3]}
/home/newuser

这样做,您只需要对该函数进行一次调用,整个数组就可以使用,而不必进行单独的查询。