当前位置: 首页>>技术教程>>正文


bash – 如何在Shell脚本中获取INI值?

, , ,

问题描述

我有一个parameters.ini文件,例如:

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

我想从bash shell脚本中读取并使用parameters.ini文件中指定的数据库版本,以便进行处理。

#!/bin/sh    
# Need to get database version from parameters.ini file to use in script    
php app/console doctrine:migrations:migrate $DATABASE_VERSION

我该怎么做?

最佳方案

然后使用awk对该行进行grepping如何

version=$(awk -F "=" '/database_version/ {print $2}' parameters.ini)

次佳方案

您可以通过以下方式使用bash本机解析器来解释ini值:

$ source <(grep = file.ini)

样本文件:

[section-a]
  var1=value1
  var2=value2
  IPS=( "1.2.3.4" "1.2.3.5" )

要访问变量,只需打印它们:echo $var1。您也可以使用上面显示的数组(echo ${IPS[@]})。

如果您只想要一个值,只需grep即可:

source <(grep var1 file.ini)

对于演示,check this recording at asciinema

这很简单,因为您不需要任何外部库来解析数据,但是它有一些缺点。例如:

  • 如果您在=之间有空格(变量名和值),则必须首先修剪空格,例如

    $ source <(grep = file.ini | sed 's/ *= */=/g')
    

    或者,如果您不关心空格(包括中间的空格),请使用:

    $ source <(grep = file.ini | tr -d ' ')
    
  • 要支持;注释,请将其替换为#

    $ sed "s/;/#/g" foo.ini | source /dev/stdin
    
  • 不支持这些部分(例如,如果您具有[section-name],则必须如上所述过滤掉它,例如grep =),对于其他意外错误也是如此。

    如果需要读取特定部分下的特定值,请使用grep -Asedawkex)。

    例如。

    source <(grep = <(grep -A5 '\[section-b\]' file.ini))
    

    注意:其中-A5是该部分中要读取的行数。将source替换为cat进行调试。

  • 如果您有任何解析错误,请通过添加以下内容来忽略它们:2>/dev/null

另请参阅:serverfault SE上的How to parse and convert ini file into bash array variables?

第三种方案

Bash不为这些文件提供解析器。显然,您可以使用awk命令或几个sed调用,但是如果您是bash-priest,并且不想使用任何其他shell,则可以尝试使用以下晦涩的代码:

#!/usr/bin/env bash
cfg_parser ()
{
    ini="$(<$1)"                # read the file
    ini="${ini//[/\[}"          # escape [
    ini="${ini//]/\]}"          # escape ]
    IFS=$'\n' && ini=( ${ini} ) # convert to line-array
    ini=( ${ini[*]//;*/} )      # remove comments with ;
    ini=( ${ini[*]/\    =/=} )  # remove tabs before =
    ini=( ${ini[*]/=\   /=} )   # remove tabs after =
    ini=( ${ini[*]/\ =\ /=} )   # remove anything with a space around =
    ini=( ${ini[*]/#\\[/\}$'\n'cfg.section.} ) # set section prefix
    ini=( ${ini[*]/%\\]/ \(} )    # convert text2function (1)
    ini=( ${ini[*]/=/=\( } )    # convert item to array
    ini=( ${ini[*]/%/ \)} )     # close array parenthesis
    ini=( ${ini[*]/%\\ \)/ \\} ) # the multiline trick
    ini=( ${ini[*]/%\( \)/\(\) \{} ) # convert text2function (2)
    ini=( ${ini[*]/%\} \)/\}} ) # remove extra parenthesis
    ini[0]="" # remove first element
    ini[${#ini[*]} + 1]='}'    # add the last brace
    eval "$(echo "${ini[*]}")" # eval the result
}

cfg_writer ()
{
    IFS=' '$'\n'
    fun="$(declare -F)"
    fun="${fun//declare -f/}"
    for f in $fun; do
        [ "${f#cfg.section}" == "${f}" ] && continue
        item="$(declare -f ${f})"
        item="${item##*\{}"
        item="${item%\}}"
        item="${item//=*;/}"
        vars="${item//=*/}"
        eval $f
        echo "[${f#cfg.section.}]"
        for var in $vars; do
            echo $var=\"${!var}\"
        done
    done
}

用法:

# parse the config file called 'myfile.ini', with the following
# contents::
#   [sec2]
#   var2='something'
cfg.parser 'myfile.ini'

# enable section called 'sec2' (in the file [sec2]) for reading
cfg.section.sec2

# read the content of the variable called 'var2' (in the file
# var2=XXX). If your var2 is an array, then you can use
# ${var[index]}
echo "$var2"

重击ini-parser可以在The Old School DevOps blog site找到。

第四种方案

Sed one-liner,其中考虑了部分。示例文件:

[section1]
param1=123
param2=345
param3=678

[section2]
param1=abc
param2=def
param3=ghi

[section3]
param1=000
param2=111
param3=222

假设您要从section2获得param2。运行以下命令:

sed -nr "/^\[section2\]/ { :l /^param2[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" ./file.ini

会给你

def

第五种方案

只需将您的.ini文件包含在bash主体中:

文件example.ini:

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

文件example.sh

#!/bin/bash
#Including .ini file
. example.ini
#Test
echo "${DBNAME}   ${DBUSER}  ${DBPASSWORD}"

第六种方案

到目前为止,我所看到的所有解决方案也都在注释行中出现。如果注释代码为;,则没有此代码:

awk -F '=' '{if (! ($0 ~ /^;/) && $0 ~ /database_version/) print $2}' file.ini

第七种方案

一种可能的解决方案之一

dbver=$(sed -n 's/.*database_version *= *\([^ ]*.*\)/\1/p' < parameters.ini)
echo $dbver

第八种方案

在ini-style my_file中显示my_key的值:

sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
  • -n-默认不打印任何内容

  • -e-执行表达式

  • s/PATTERN//p-在此模式之后显示任何内容

  • ^-模式从行的开头开始

  • \s-空格字符

  • *-零个或多个(空格字符)

例:

$ cat my_file
# Example INI file
something   = foo
my_key      = bar
not_my_key  = baz
my_key_2    = bing

$ sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
bar

所以:

Find a pattern where the line begins with zero or many whitespace characters, followed by the string my_key, followed by zero or many whitespace characters, an equal sign, then zero or many whitespace characters again. Display the rest of the content on that line following that pattern.

第九种方案

sed

您可以使用sed来解析ini配置文件,尤其是当您拥有以下部分名称时:

# last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
# use IP address in case network name resolution is not working
server=192.0.2.62
port=143
file=payroll.dat

因此您可以使用以下sed脚本来解析上述数据:

# Configuration bindings found outside any section are given to
# to the default section.
1 {
  x
  s/^/default/
  x
}

# Lines starting with a #-character are comments.
/#/n

# Sections are unpacked and stored in the hold space.
/\[/ {
  s/\[\(.*\)\]/\1/
  x
  b
}

# Bindings are unpacked and decorated with the section
# they belong to, before being printed.
/=/ {
  s/^[[:space:]]*//
  s/[[:space:]]*=[[:space:]]*/|/
  G
  s/\(.*\)\n\(.*\)/\2|\1/
  p
}

这会将ini数据转换为这种平面格式:

owner|name|John Doe
owner|organization|Acme Widgets Inc.
database|server|192.0.2.62
database|port|143
database|file|payroll.dat

因此通过在每一行中都有节名称,可以更轻松地使用sedawkread进行解析。

积分和来源:Configuration files for shell scripts,迈克尔·格鲁尼瓦尔德(MichaelGrünewald)


或者,您可以使用以下项目:chilladx/config-parser,这是使用sed的配置解析器。

第十种方案

对于希望从shell脚本中读取INI文件(例如读取shell,而不是bash)的人(像我一样)-我打开了一个小助手库,它试图做到这一点:

https://github.com/wallyhall/shini(MIT许可证,请随意使用。由于代码很长,我已经在上面链接了它的内嵌代码。)

它比上面建议的简单sed行要多一些”complicated”-但工作原理非常相似。

函数读取文件line-by-line-查找节标记([section])和键/值声明(key=value)。

最终,您将获得自己函数的回调-部分,键和值。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/10552.html,未经允许,请勿转载。