在bash中读取包含多个变量的数据文件

在bash中读取包含多个变量的数据文件,bash,Bash,我想从bash中的数据文件中读取以下变量 #/tmp/input.dat $machie=1234-567*890ABC $action=REPLACE $location=test_location 谢谢你的帮助 助教/usr/bin/env bash 案例$BASH_版本 ''|[0-3].*)echo“错误:需要Bash 4.0或更新版本”>&2;出口1;; 以撒 #从命令行读取输入文件名,默认为“/tmp/input.dat” input_file=${1:-/tmp/input.da

我想从bash中的数据文件中读取以下变量

#/tmp/input.dat
$machie=1234-567*890ABC
$action=REPLACE
$location=test_location
谢谢你的帮助

助教/usr/bin/env bash 案例$BASH_版本 ''|[0-3].*)echo“错误:需要Bash 4.0或更新版本”>&2;出口1;; 以撒 #从命令行读取输入文件名,默认为“/tmp/input.dat” input_file=${1:-/tmp/input.dat} 声明-A变量=() 而IFS=读取-r行;做 [[$line=“#“*]”和&continue#跳过输入中的注释 [[$line=*=*]| |继续#跳过不包含“=”的行 行=${line#'$'}#条带前导“$” key=${line%%=*}#删除第一个“=”之后的所有内容以获取密钥 value=${line#*=}#删除第一个“=”之前的所有内容以获取值 vars[$key]=$value#将键/值对添加到关联数组 完成&2 echo“操作为${vars[action]};位置为${vars[location]}”>&2
见:

  • -如何逐行(和/或逐字段)读取文件(数据流、变量)
  • -如何使用变量(间接变量、指针、引用)或关联数组?;这里,我们使用的是关联数组,但您可以使用相同的技术直接指定给命名变量。[1]
  • ,用于分隔每行的“键”和“值”部分的语法;也包括在

[1] -请注意,如果您不打算使用关联数组,如本回答中所建议的,出于安全原因,最好使用带前缀的命名空间:
printf-v“var\u$key”%s“$value”
——生成变量名时,您将取消引用为
$var\u action
$var\u location
——比
printf-v安全得多“$key”%s“$value”
,因为前者确保数据文件不会覆盖安全关键环境变量,如
PATH
LD_PRELOAD
,从而导致此类尝试无害地设置
$var_PATH
$var_LD_PRELOAD
!/usr/bin/env bash
案例$BASH_版本
''[0-3].*)echo“错误:需要Bash 4.0或更新版本”>&2;退出1;;
以撒
#从命令行读取输入文件名,默认为“/tmp/input.dat”
input_file=${1:-/tmp/input.dat}
声明-A变量=()
当IFS=读取-r行时;执行
[[$line=“#“*]”和&continue#跳过输入中的注释
[[$line=*=*]| |继续#跳过不包含“=”的行
行=${line#'$'}#条带前导“$”
key=${line%%=*}#删除第一个“=”之后的所有内容以获取密钥
value=${line#*=}#删除第一个“=”之前的所有内容以获取值
vars[$key]=$value#将键/值对添加到关联数组
完成&2
echo“操作是${vars[action]};位置为${vars[location]}“>&2

见:

  • -如何逐行(和/或逐字段)读取文件(数据流、变量)
  • -如何使用变量(间接变量、指针、引用)或关联数组?这里,我们使用关联数组,但您可以使用相同的技术直接指定给命名变量。[1]
  • ,用于分隔每行的“键”和“值”部分的语法;也包括在中


[1] -请注意,如果您不打算使用关联数组,如本回答中所建议的,出于安全原因,最好使用带前缀的命名空间:
printf-v“var\u$key”%s“$value”
——生成变量名时,您将取消引用为
$var\u action
$var\u location
——比
printf-v]安全得多$key“%s”$value“
,因为前者确保您的数据文件不会覆盖安全关键环境变量,例如
PATH
LD\u PRELOAD
,从而导致此类尝试以无害的方式设置
$var\u PATH
$var\u LD\u PRELOAD

是否控制输入格式?@CharlesDuffy yes,我知道。如果您没有前导的
$
s,您的输入文件将是一个有效的shell脚本,因此您可以
source/tmp/input.dat
在当前解释器中执行它。当然,这意味着当以这种方式解析时,您需要相信它的内容不会做任何恶意的事情(即使是无意的!);如果代码不是由了解相关规则的人手工编写的,那么使用知道如何进行正确的shell转义的代码生成它会更安全。您控制输入格式吗?@CharlesDuffy是的,我控制。如果您没有前导的
$
s,您的输入文件将是有效的shell脚本,因此,您可以
source/tmp/input.dat
在当前解释器中执行它。当然,这意味着当以这种方式解析时,您需要相信它的内容不会做任何恶意的事情(即使是无意的!);如果代码不是由了解相关规则的人手工编写的,那么使用知道如何进行适当的shell转义的代码生成它会更安全。
#!/usr/bin/env bash
case $BASH_VERSION in
  ''|[0-3].*) echo "ERROR: Bash 4.0 or newer is required" >&2; exit 1;;
esac

# read input filename from command line, default to "/tmp/input.dat"
input_file=${1:-/tmp/input.dat}

declare -A vars=()

while IFS= read -r line; do
  [[ $line = "#"* ]] && continue  # Skip comments in input
  [[ $line = *=* ]]  || continue  # Skip lines not containing an "="
  line=${line#'$'}                # strip leading "$"
  key=${line%%=*}                 # remove everything after first "=" to get key
  value=${line#*=}                # remove everything before first "=" to get value
  vars[$key]=$value               # add key/value pair to associative array
done <"$input_file"

# print the variables we read for debugging purposes
declare -p vars >&2

echo "Operation is ${vars[action]}; location is ${vars[location]}" >&2