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

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

How do I grab an INI value within a shell script?

bashshellconfigini

提问by Stephen Watkins

I have a parameters.ini file, such as:

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

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

I want to read in and use the database version specified in the parameters.ini file from within a bash shell script so I can process it.

我想从 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

How would I do this?

我该怎么做?

采纳答案by Ali Lown

How about grepping for that line then using awk

如何grepping该行然后使用awk

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

回答by kenorb

You can use bash native parser to interpret ini values, by:

您可以使用 bash 本机解析器来解释 ini 值,方法是:

$ source <(grep = file.ini)

Sample file:

示例文件:

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

To access variables, you simply printing them: echo $var1. You may also use arrays as shown above (echo ${IPS[@]}).

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

If you only want a single value just grep for it:

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

source <(grep var1 file.ini)

For the demo, check this recording at asciinema.

对于演示,请在 asciinema 检查此录音

It is simple as you don't need for any external library to parse the data, but it comes with some disadvantages. For example:

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

  • If you have spaces between =(variable name and value), then you've to trim the spaces first, e.g.

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

    Or if you don't care about the spaces (including in the middle), use:

    $ source <(grep = file.ini | tr -d ' ')
    
  • To support ;comments, replace them with #:

    $ sed "s/;/#/g" foo.ini | source /dev/stdin
    
  • The sections aren't supported (e.g. if you've [section-name], then you've to filter it out as shown above, e.g. grep =), the same for other unexpected errors.

    If you need to read specific value under specific section, use grep -A, sed, awkor ex).

    E.g.

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

    Note: Where -A5is the number of rows to read in the section. Replace sourcewith catto debug.

  • If you've got any parsing errors, ignore them by adding: 2>/dev/null

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

    $ 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节中要读取的行数在哪里。替换sourcecat调试。

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

See also: How to parse and convert ini file into bash array variables?at serverfault SE

另请参阅:如何解析 ini 文件并将其转换为 bash 数组变量?在服务器故障 SE

回答by Fredrik Pihl

Bash does not provide a parser for these files. Obviously you can use an awk command or a couple of sed calls, but if you are bash-priest and don't want to use any other shell, then you can try the following obscure code:

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

#!/usr/bin/env bash
cfg_parser ()
{
    ini="$(<)"                # 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
}

Usage:

用法:

# 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"

Bash ini-parser can be found at The Old School DevOps blog site.

Bash ini-parser 可以在The Old School DevOps 博客站点上找到

回答by egridasov

Sed one-liner, that takes sections into account. Example file:

Sed one-liner,将部分考虑在内。示例文件:

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

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

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

Say you want param2 from section2. Run the following:

假设您想要第 2 节中的 param2。运行以下命令:

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

will give you

会给你

def

回答by Gustavo González

Just include your .ini file into bash body:

只需将您的 .ini 文件包含到 bash 正文中:

File example.ini:

文件example.ini

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

File example.sh

文件example.sh

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

回答by Opux

All of the solutions I've seen so far also hit on commented out lines. This one didn't, if the comment code is ;:

到目前为止,我看到的所有解决方案也都出现在注释掉的行上。这个没有,如果评论代码是;

awk -F '=' '{if (! (
dbver=$(sed -n 's/.*database_version *= *\([^ ]*.*\)//p' < parameters.ini)
echo $dbver
~ /^;/) &&
sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
~ /database_version/) print }' file.ini

回答by jm666

one of more possible solutions

更多可能的解决方案之一

$ 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

回答by Dean Rather

Display the value of my_keyin an ini-style my_file:

在 ini 样式的my_file 中显示my_key的值:

# 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
  • -n-- do not print anything by default
  • -e-- execute the expression
  • s/PATTERN//p-- display anything following this pattern In the pattern:
  • ^-- pattern begins at the beginning of the line
  • \s-- whitespace character
  • *-- zero or many (whitespace characters)
  • -n-- 默认不打印任何内容
  • -e-- 执行表达式
  • s/PATTERN//p-- 显示任何遵循此模式的内容 在模式中:
  • ^-- 模式从行首开始
  • \s-- 空白字符
  • *-- 零个或多个(空白字符)

Example:

例子:

# 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/\[\(.*\)\]//
  x
  b
}

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

So:

所以:

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.

找到一个模式,其中该行以零个或多个空白字符开头,后跟字符串my_key,然后是零个或多个空白字符,一个等号,然后又是零个或多个空白字符。按照该模式显示该行上的其余内容。

回答by kenorb

sed

sed

You can use sedto parse the ini configuration file, especially when you've section names like:

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

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

so you can use the following sedscript to parse above data:

所以你可以使用下面的sed脚本来解析上面的数据:

##代码##

this will convert the ini data into this flat format:

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

##代码##

so it'll be easier to parse using sed, awkor readby having section names in every line.

所以它会更容易使用解析sedawk或者read通过在每行有节的名称。

Credits & source: Configuration files for shell scripts, Michael Grünewald

积分和来源:shell 脚本的配置文件,Michael Grünewald



Alternatively, you can use this project: chilladx/config-parser, a configuration parser using sed.

或者,您可以使用这个项目:chilladx/config-parser,一个使用sed.

回答by wally

For people (like me) looking to read INI files from shell scripts (read shell, not bash) - I've knocked up the a little helper library which tries to do exactly that:

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

https://github.com/wallyhall/shini(MIT license, do with it as you please. I've linked above including it inline as the code is quite lengthy.)

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

It's somewhat more "complicated" than the simple sedlines suggested above - but works on a very similar basis.

它比sed上面建议的简单线条更“复杂” - 但工作原理非常相似。

Function reads in a file line-by-line - looking for section markers ([section]) and key/value declarations (key=value).

函数逐行读取文件 - 查找部分标记 ( [section]) 和键/值声明 ( key=value)。

Ultimately you get a callback to your own function - section, key and value.

最终你会得到一个你自己的函数的回调——部分、键和值。