在 Bash 中解析配置文件中的变量

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

Parsing variables from config file in Bash

bashparsingvariablesawk

提问by KillDash9

Having the following content in a file:

在文件中包含以下内容:

VARIABLE1="Value1"
VARIABLE2="Value2"
VARIABLE3="Value3"

I need a script that outputs the following:

我需要一个输出以下内容的脚本:

Content of VARIABLE1 is Value1
Content of VARIABLE2 is Value2
Content of VARIABLE3 is Value3

Any ideas?

有任何想法吗?

回答by glenn Hymanman

Since your config file is a valid shell script, you can source it into your current shell:

由于您的配置文件是一个有效的 shell 脚本,您可以将它的源代码导入当前的 shell:

. config_file
echo "Content of VARIABLE1 is $VARIABLE1"
echo "Content of VARIABLE2 is $VARIABLE2"
echo "Content of VARIABLE3 is $VARIABLE3"

Slightly DRYer, but trickier

稍微干燥,但更棘手

. config_file
for var in VARIABLE1 VARIABLE2 VARIABLE3; do
    echo "Content of $var is ${!var}"
done

回答by antonio

If you need these...

如果你需要这些...

Features

特征

  • Single line and inline comments;
  • Trimming spaces around =(ie var = valuewill not fail);
  • Quoted string values;
  • Understanding of DOS line endings;
  • Keep safe, avoiding sourcing your config file.
  • 单行和内联注释;
  • 修剪周围的空间=(即var = value不会失败);
  • 带引号的字符串值;
  • 了解DOS行尾;
  • 保持安全,避免获取您的配置文件。

Code

代码

shopt -s extglob
configfile="dos_or_unix" # set the actual path name of your (DOS or Unix) config file
tr -d '\r' < $configfile > $configfile.unix
while IFS='= ' read -r lhs rhs
do
    if [[ ! $lhs =~ ^\ *# && -n $lhs ]]; then
        rhs="${rhs%%\#*}"    # Del in line right comments
        rhs="${rhs%%*( )}"   # Del trailing spaces
        rhs="${rhs%\"*}"     # Del opening string quotes 
        rhs="${rhs#\"*}"     # Del closing string quotes 
        declare $lhs="$rhs"
    fi
done < $configfile.unix

Comments

注释

tr -d '\r' ...deletes DOS carriage return.
! $lhs =~ ^\ *#skips single line comments and -n $lhsskips empty lines.
Deleting trailing spaces with ${rhs%%*( )}requires setting extended globbing with shopt -s extglob. (Apart using sed), you can avoid this, via the more complex:

tr -d '\r' ...删除 DOS 回车。
! $lhs =~ ^\ *#跳过单行注释并-n $lhs跳过空行。
删除尾随空格${rhs%%*( )}需要使用shopt -s extglob. (除了使用sed),您可以通过更复杂的方式避免这种情况:

rhs="${rhs%"${rhs##*[^ ]}"}"  

Test config file

测试配置文件

## This is a comment 
var1=value1             # Right side comment 
var2 = value2           # Assignment with spaces 

## You can use blank lines 
var3= Unquoted String   # Outer spaces trimmed
var4= "My name is "     # Quote to avoid trimming 
var5= "\"Bob\""         

Test code

测试代码

echo "Content of var1 is $var1"
echo "Content of var2 is $var2"
echo "Content of var3 is [$var3]"
echo "Content of var4 + var5 is: [$var4$var5]"

Results

结果

Content of var1 is value1
Content of var2 is value2
Content of var3 is [Unquoted String]
Content of var4 + var5 is: [My name is "Bob"]

回答by abasu

awk -F\= '{gsub(/"/,"",$2);print "Content of " $1 " is " $2}' <filename>

awk -F\= '{gsub(/"/,"",$2);print "Content of " $1 " is " $2}' <filename>

Just FYI, another pure bash solution

仅供参考,另一个纯 bash 解决方案

IFS="="
while read -r name value
do
echo "Content of $name is ${value//\"/}"
done < filename

回答by albert

I do in this way

我这样做

. $PATH_TO_FILE

回答by Steven Penny

awk '{print "Content of "" is "}' FS='[="]'

Result

结果

Content of VARIABLE1 is Value1
Content of VARIABLE2 is Value2
Content of VARIABLE3 is Value3

回答by Yordan Georgiev

    # 
    #------------------------------------------------------------------------------
    # parse the ini like 
[a]
b=C
d=E;rm t1
[b]
g=h
.$host_name.cnf and set the variables # cleans the unneeded during after run-time stuff. Note the MainSection # courtesy of : http://mark.aufflick.com/blog/2007/11/08/parsing-ini-files-with-sed #------------------------------------------------------------------------------ doParseConfFile(){ # set a default cnfiguration file cnf_file="$run_unit_bash_dir/$run_unit.cnf" # however if there is a host dependant cnf file override it test -f "$run_unit_bash_dir/$run_unit.$host_name.cnf" \ && cnf_file="$run_unit_bash_dir/$run_unit.$host_name.cnf" # yet finally override if passed as argument to this function # if the the ini file is not passed define the default host independant ini file test -z "" || cnf_file=;shift 1; test -z "" || ini_section=;shift 1; doLog "DEBUG read configuration file : $cnf_file" doLog "INFO read [$ini_section] section from config file" # debug echo "@doParseConfFile cnf_file:: $cnf_file" # coud be later on parametrized ... test -z "$ini_section" && ini_section='MAIN_SETTINGS' doLog "DEBUG reading: the following configuration file" doLog "DEBUG ""$cnf_file" ( set -o posix ; set ) | sort >"$tmp_dir/vars.before" eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \ -e 's/#.*$//' \ -e 's/[[:space:]]*$//' \ -e 's/^[[:space:]]*//' \ -e "s/^\(.*\)=\([^\"']*\)$/=\"\"/" \ < $cnf_file \ | sed -n -e "/^\[$ini_section\]/,/^\s*\[/{/^[^#].*\=.*/p;}"` ( set -o posix ; set ) | sort >"$tmp_dir/vars.after" doLog "INFO added the following vars from section: [$ini_section]" cmd="$(comm -3 $tmp_dir/vars.before $tmp_dir/vars.after | perl -ne 's#\s+##g;print "\n $_ "' )" echo -e "$cmd" echo -e "$cmd" >> $log_file echo -e "\n\n" sleep 1; printf "3[2J";printf "3[0;0H" # and clear the screen } #eof func doParseConfFile

回答by Rich Armstrong

given a config file as follows :-

给出一个配置文件如下:-

CFG=path-to-file; for ini in `awk '/^\[/' $CFG`;do unset ARHG;declare -A ARHG;while read A B;do ARHG[$A]=$B;echo "in section $ini, $A is equal to"  ${ARHG["$A"]};done < <(awk -F'=' '/\[/ {x=0} x==1 && 
CFG=path-to-file;
for ini in `awk '/^\[/' $CFG` # finds the SECTIONS (aka "ini")
do 
  unset ARHG # resets ARHG 
  declare -A ARHG # declares an associative array
  while read A B
  do
    ARHG[$A]=$B
    echo "in section $ini, $A is equal to"  ${ARHG["$A"]}
  done < <(awk -F'=' '/\[/ {x=0} x==1 && ##代码##~/=/ && NF==2 {print , } ##代码##==INI {x=1}' INI="$ini" $CFG)
  # the awk splits the file into sections, 
  # and returns pairs of values separated by "="
  declare -p ARHG # displays the current contents of ARHG
  echo
done
printf "end loop\n\n"
declare -p ARHG
~/=/ && NF==2 {print , } ##代码##==INI {x=1}' INI="$ini" $CFG);declare -p ARHG;echo;done;printf "end loop\n\n";declare -p ARHG

the following one-liner will parse and hold the values :-

以下单行代码将解析并保存值:-

##代码##

Now, let's break that down

现在,让我们分解一下

##代码##

This allows us to save values, without using eval or backtick. To be "really clean", we could remove [:space:] at the start and end of line, ignore "^#" lines, and remove spaces around the "equals" sign.

这允许我们保存值,而无需使用 eval 或反引号。为了“真正干净”,我们可以删除行首和行尾的 [:space:] ,忽略“^#”行,并删除“等号”周围的空格。