Bash 从外部文件读取数组

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

Bash read array from an external file

bash

提问by jmituzas

I have setup a Bash menu script that also requires user input. These inputs are wrote (appended to) a text file named var.txt like so:

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

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

Now what I am trying to accomplish is to be able to read from var.txt from a script kinda like this:

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

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

now I know that wont work just using it for an example.

现在我知道仅以它为例是行不通的。

Thanks in Advance, Joe

提前致谢,乔

采纳答案by Paused until further notice.

You can encapsulate your variable extraction in a function and take advantage of the fact that declarecreates local variables when used inside a function. This technique reads the file each time the function is called.

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

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

Given a file called "data" containing:

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

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

You could do:

你可以这样做:

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

This will read an array and rename it:

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

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 < ""
    local d=$(declare -p )
    echo ${d/#declare -a /declare -a ${3:-}};
}

Examples:

例子:

$ 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

Doing it this way, you would only need to make one call to the function and the entire array would be available instead of having to make individual queries.

通过这种方式,您只需调用一次该函数,整个数组就可用,而不必进行单独的查询。

回答by thejoshwolfe

Use bash's readarraystatement. (It's the only way I can find to put spaces in array elements dynamically.) You'll need your var.txtfile to simply contain the elements of the array, one on each line, not contain assignment statements.

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

readarray -t input < var.txt

For more info, try help readarray(which will then tell you to try help mapfile).

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

Here's my test for it:

这是我的测试:

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

prints:

印刷:

a
b c
d

Note: doing cat var.txt | readarray -t inputdoesn't work. I think it's because the inputvariable is scoped out of reach.

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

回答by thkala

If the whole var.txtfile contains only Bash-compatible variable assignments as you indicated, you might just be able to sourceit, to make those variables available in a new Bash script:

如果整个var.txt文件只包含bash兼容的变量赋值为你指出,你可能只是能够采购它,使这些变量可以在一个新的bash脚本:

source var.txt

useradd ${input[1]}

This, however, will overwrite any existing variable with the same name. Command substitutioncan be used to avoid this, by selecting specific variables:

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

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

It allows for renaming variables, although you will have to do this for each variable of interest. It essentially extracts the value of the variable from the var.txtfile and assigns it to a new variable. See the grep manual pageand the sed info pagefor more information on their use.

它允许重命名变量,尽管您必须为每个感兴趣的变量执行此操作。它本质上是从var.txt文件中提取变量的值并将其分配给一个新变量。有关其使用的更多信息,请参阅grep 手册页sed 信息页

Process substitutionmay allow for simpler expressions:

进程替换可能允许更简单的表达式:

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

useradd ${input[1]}

This would allow you to import only definitions of interest, although you have to watch for unwanted variable overwrites.

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