【问题标题】:Reading a config file from a shell script从 shell 脚本中读取配置文件
【发布时间】:2011-08-24 10:09:14
【问题描述】:

我正在寻找类似于 Python 的 ConfigParser 或 Perl 的 Config::INI 的 shell 脚本。我过去曾采购过文件来完成此操作,但我更愿意阅读而不是执行我的“配置文件”。有谁知道与上述可用于 shell(或 bash)脚本的模块相媲美的东西?

谢谢, 杰瑞

【问题讨论】:

标签: shell config


【解决方案1】:

您不想获取它,所以您应该:

1.读取配置,2.验证行 3.评估它们

CONFIGFILE="/path/to/config"
echo "=$ADMIN= =$TODO= =$FILE=" #these variables are not defined here
eval $(sed '/:/!d;/^ *#/d;s/:/ /;' < "$CONFIGFILE" | while read -r key val
do
    #verify here
    #...
    str="$key='$val'"
    echo "$str"
done)
echo =$ADMIN= =$TODO= =$FILE= #here are defined

配置文件示例

ADMIN: root
TODO: delete

var=badly_formtatted_line_without_colon

#comment
FILE: /path/to/file

如果你运行上面的示例应该得到(未测试):

== == ==
=root= =delete= =/path/to/file=

确定这不是最好的解决方案 - 也许有人会发布一个更好的解决方案。

【讨论】:

  • 我想我在想一些像 ConfigParser 这样的预打包的东西,但这确实有效。谢谢!
  • 处理配置文件中的空行:eval $(sed '/^ *#/d;s/:/ /;' &lt; "$CONFIGFILE" | while read key val do if [ -n "${key}" ]; then str="$key='$val'" echo "$str" fi done)
  • @slonik 处理空行的好方法。在脚本中,sed 过滤掉了不需要的行,因此足以添加到 sed 另一个命令,例如:/^ *$/d(例如,删除仅包含任意数量空格的行 - 例如零个或多个)。谢谢你指出我的问题。编辑了我的答案。
  • @slonik 实际上,添加了一个命令来删除任何不包含冒号 : 的行,因为它是必不可少的。
【解决方案2】:

你可能想看看cfget 可以用sudo apt-get install cfget 安装。

【讨论】:

  • 如果您有权在您的系统上安装它,这是一个非常有用的工具。
【解决方案3】:
#!/bin/bash 
# Author: CJ
# Date..: 01/03/2013

## sample INI file save below to a file, replace "^I" with tab
#^I [    SECTION ONE     ]  
#TOKEN_TWO^I ="Value1 two   "
#TOKEN_ONE=Value1 One
#TOKEN_THREE=^I"Value1^I three" # a comment string
#TOKEN_FOUR^I=^I"^IValue1 four"
#
#[SECTION_TWO]  
#TOKEN_ONE=Value1 One ^I^I^I# another comment string
#TOKEN_TWO^I ="Value1 two   "
#TOKEN_THREE=^I"Value1^I three"
#TOKEN_FOUR^I=^I"^IValue1 four"
## sample INI file

export INI= # allows access to the parsed INI values in toto by children
iniParse() {
    # Make word separator Linefeed(\n)
    OIFS="${IFS}"
    IFS=$(echo)

    SECTION=_
    while read LINE; do {
        IFS="${OIFS}"

        # Skip blank lines
        TMP="$(echo "${LINE}"|sed -e "s/^[ \t]*//")"
        if [ 0 -ne ${#TMP} ]; then
            # Ignore comment lines
            if [ '#' == "${LINE:0:1}" -o '*' == "${LINE:0:1}" ]; then
                continue
            fi # if [ '#' == "${LINE:0:1}" -o '*' == "${LINE:0:1}" ]; then

            # Section label
            if [ "[" == "${LINE:0:1}" ]; then
                LINE="${LINE/[/}"
                LINE="${LINE/]/}"
                LINE="${LINE/ /_}"
                SECTION=$(echo "${LINE}")_
            else
                LINE="$(echo "${LINE}"|sed -e "s/^[ \t]*//")"
                LINE="$(echo "${LINE}"|cut -d# -f1)"

                TOKEN="$(echo "${LINE:0}"|cut -d= -f1)"
                EQOFS=${#TOKEN}
                TOKEN="$(echo "${TOKEN}"|sed -e "s/[ \t]*//g")"

                VALUE="${LINE:${EQOFS}}"
                VALUE="$(echo "${VALUE}"|sed -e "s/^[ \t=]*//")"
                VALUE="$(echo "${VALUE}"|sed -e "s/[ \t]*$//")"

                if [ "${VALUE:0:1}" == '"' ]; then
                    echo -n "${SECTION}${TOKEN}=${VALUE}"
                    echo -e "\r"
                else
                    echo -n "${SECTION}${TOKEN}="\"${VALUE}\"""
                    echo -e "\r"
                fi # if [ "${VALUE:0:1}" == '"' ]; then
            fi # if [ "[" == "${LINE:0:1}" ]; then 
        fi # if [ 0 -ne ${#TMP} ]; then

        IFS=$(echo)
    } done <<< "$1"

    IFS="${OIFS}" # restore original IFS value
} # iniParse()

# call this function with the INI filespec
iniReader() {
    if [ -z "$1" ]; then return 1; fi

    TMPINI="$(<$1)"
    TMPINI="$(echo "${TMPINI}"|sed -e "s/\r//g")"
    TMPINI="$(echo "${TMPINI}"|sed -e "s/[ \t]*\[[ \t]*/[/g")"
    TMPINI="$(echo "${TMPINI}"|sed -e "s/[ \t]*\][ \t]*/]/g")"

    INI=`iniParse "${TMPINI}"`
    INI="$(echo "${INI}"|sed -e "s/\r/\n/g")"
    eval "${INI}"

    return 0
} # iniReader() {

# sample usage
if iniReader $1 ; then
    echo INI read, exit_code $? # exit_code == 0
    cat <<< "${INI}"
    cat <<< "${SECTION_ONE_TOKEN_FOUR}"
    cat <<< "${SECTION_ONE_TOKEN_THREE}"
    cat <<< "${SECTION_TWO_TOKEN_TWO}"
    cat <<< "${SECTION_TWO_TOKEN_ONE}"
else
    echo usage: $0 filename.ini
fi # if iniReader $1 ; then

【讨论】:

    【解决方案4】:

    基于grep 的替代方案似乎更具可读性:

    CONFIG_FILE='/your/config/file.ini'
    eval $(grep '^\[\|^#' CONFIG_FILE -v | while read line
      do echo $line
    done)
    

    地点:

    • -v grep 选项表示排除匹配行
    • ^\[\|^# 选择所有以 [ 或 # 开头的行(configparser 部分和 cmets)

    仅当您的配置文件在 = 周围没有空格时才有效(如果您想使用 Python 生成配置,请使用 space_around_delimiters=False 参见 https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.write)

    支持的配置示例:

    FIRST_VAR="a"
    
    [lines started with [ will be ignored]
    secondvar="b"
    
    # some comment
    anotherVar="c"
    

    【讨论】:

      【解决方案5】:

      您可以使用 bash it-self 来解释 ini 值,方法是:

      $ source <(grep = file.ini)
      

      示例文件:

      [section-a]
        var1=value1
        var2=value2
      

      查看更多示例:How do I grab an INI value within a shell script?

      或者您可以使用 bash ini-parser,它可以在 The Old School DevOps blog site 找到。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-29
        • 2019-11-13
        • 2017-09-01
        相关资源
        最近更新 更多