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


97

我有一个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

我该怎么做?


2
这些答案中的任何一个都完全尊重章节吗?
ManuelSchneid3r

Answers:


83

如何使用awk对该行进行grepping

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

6
这将在'='之后包含空格。

10
要修剪空格,请| tr -d ' '在末尾添加。
kenorb 2015年

22
这并不是一个很好的解决方案。考虑有2个[parameters.ini]节,每个节都有一个'database_version'变量。然后,您将获得两次该值。
nerdoc

4
是的,请考虑使用像crudini这样的专用ini解析器,因为上面没有处理很多边缘情况
pixelbeat 2015年

3
对于基本的ini文件仍然有用且快捷。
西里尔N.16年

51

您可以通过以下方式使用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)

对于演示,请在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是本节中要读取的行数。替换sourcecat进行调试。

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

也可以看看:


1
但是... source <(grep = <(grep -A5 '\[section-b\]' file.ini))这将不起作用:[sec a] a = 1 b = 2 c = 3 [sec b] a = 2 b = 3 [sec c] a = 0。没有明确规则的地方
Psychozoic,

我尝试使用source,但是当我回显$ var1时,它什么也不返回。为什么?
A. Gh

@ A.Gh我不确定,为我工作。确保您使用的是Bash shell。参见:asciinema.org/a/306481
kenorb

这本来不错,但是无法在OS X(Catalina)中使用。它可以在zsh(当前默认外壳程序)中的命令提示符下工作,但是一旦将其放入脚本中,就会收到错误消息syntax error near unexpected token '('。使用bash时,它在提示和脚本中均无提示地失败。
MiRin

29

Bash不为这些文件提供解析器。显然,您可以使用awk命令或几个sed调用,但是如果您是bash牧师并且不想使用任何其他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"

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


3
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
alecxe

8
我通常是这样发表评论的人。我只能说我年轻又愚蠢:-)
弗雷德里克·皮尔

1
如果您喜欢此片段,请访问github.com/albfan/bash-ini-parser
albfan

3
要正常工作,需要使用cfg_parser代替cfg.parser的
韦斯

1
TYPO:“ cfg.parser”应为“ cfg_parser”。
Setop

26

sed单线,考虑了部分。示例文件:

[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

3
sed -nr“ / ^ \ [SECTION2 \] / {:l /^\s*[^#].*/ p; n; / ^ \ [/ q; bl;}” file.conf#获取整个节对于带有[SECTION2]和#个哈希样式注释行的.conf样式文件,不包含注释。如果只需要一个参数,则使用grep表示参数名。
盖伊兹

比阅读下"/^\[section2\]/,/^\[/{...}"
盆地

1
如果在Mac:brew install gnu-sed然后使用gsed(否则:sed: illegal option -- r
frnhr

谁能解释该 sed -nr "/^\[SECTION2\]/ { :l /^\s*[^#].*/ p; n; /^\[/ q; b l; }" 表达式的工作原理?谢谢
foo_l

22

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

文件example.ini

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

文件example.sh

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

2
这应该是选定的答案。它确实与file.properties一起使用,并且具有容错能力(文件中带有空行)。谢谢
安东尼

17
不处理INI文件的[section]部分。
Setop

这是最好的答案!
JavaSheriff

17
希望没有人在ini文件中添加“ rm -rf /” :(
HeyMan

1
子外壳中的安全得多:$(。example.ini; echo $ DBNAME)
Rich Remer

14

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

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

2
这应该是公认的答案,因为a)它处理注释掉的行b)简单:)
Sudar

1
太好了,ty @PenguinLust!用法:1.允许使用分号前缀的全行注释(不允许行内注释);2.结果中没有空格(因此,如果ini文件具有“ a = 1”,则脚本对“ a”的搜索将得出“ 1”)。
AnneTheAgile 2014年

1
要修剪空格,请| tr -d ' '在末尾添加。
kenorb

这和建议的答案有同样的问题。它搜索“ database_version”的每个实例
Nubcake

12

一种可能的解决方案之一

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

8

以ini风格的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

所以:

查找一个模式,该行以零个或多个空格字符开头,然后是字符串my_key,然后是零个或多个空格字符,等号,然后又是零个或多个空格字符。在该模式之后,在该行上显示其余内容。


您的示例bar至少在Unix / OSX上不起作用(不打印出来)。
kenorb

7

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

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

鸣谢与出处:Shell脚本的配置文件,MichaelGrünewald


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


这很棒!我当时正在考虑将其扁平化,但是这比我要一起破解的东西还差很多!
grinch

6

您可以使用crudini工具获取ini值,例如:

DATABASE_VERSION=$(crudini --get parameters.ini '' database_version)

请注意,它基于Python,因此可能不适用于嵌入式Linux应用程序。
Craig McQueen 2015年

这是标准Fedora存储库的一部分(已通过31测试)。 yum install crudini
shrewmouse

5

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

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

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

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

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


@CraigMcQueen-今晚我添加了一些非常具有alpha品质的写支持。凭空想像还不是“完整的”!
wally

辉煌!:-) Major
Jonathan

5

与其他Python答案类似,您可以使用该-c标志来执行命令行上给出的一系列Python语句:

$ python3 -c "import configparser; c = configparser.ConfigParser(); c.read('parameters.ini'); print(c['parameters.ini']['database_version'])"
20110611142248

这具有仅需要Python标准库的优势,而无需编写单独的脚本文件的优势。

或使用here文档以获得更好的可读性,因此:

#!/bin/bash
python << EOI
import configparser
c = configparser.ConfigParser()
c.read('params.txt')
print c['chassis']['serialNumber']
EOI

serialNumber=$(python << EOI
import configparser
c = configparser.ConfigParser()
c.read('params.txt')
print c['chassis']['serialNumber']
EOI
)

echo $serialNumber

如果我想使用此命令将整个节抓取为数组怎么办?
Debopam Parua '19

2

有些答案不尊重评论。有些人不尊重章节。有些人仅识别一种语法(仅“:”或“ =“)。由于大小写不同或无法导入sys模块,某些Python解答在我的计算机上失败。对我来说,一切都太紧了。

因此,我编写了自己的代码,如果您拥有现代的Python,则可以从Bash shell调用它。它具有遵守某些常见的Python编码约定的优势,甚至还提供了明智的错误消息和帮助。要使用它,请将其命名为myconfig.py之类的名称(请勿将其命名为configparser.py,否则可能会尝试自行导入),使其可执行,然后像调用它一样

value=$(myconfig.py something.ini sectionname value)

这是我在Linux上使用Python 3.5的代码:

#!/usr/bin/env python3
# Last Modified: Thu Aug  3 13:58:50 PDT 2017
"""A program that Bash can call to parse an .ini file"""

import sys
import configparser
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="A program that Bash can call to parse an .ini file")
    parser.add_argument("inifile", help="name of the .ini file")
    parser.add_argument("section", help="name of the section in the .ini file")
    parser.add_argument("itemname", help="name of the desired value")
    args = parser.parse_args()

    config = configparser.ConfigParser()
    config.read(args.inifile)
    print(config.get(args.section, args.itemname))

2

复杂的简单

INI文件

test.ini

[section1]
name1=value1
name2=value2
[section2]
name1=value_1
  name2  =  value_2

具有读取和执行功能的bash脚本

/ bin / parseini

#!/bin/bash

set +a
while read p; do
  reSec='^\[(.*)\]$'
  #reNV='[ ]*([^ ]*)+[ ]*=(.*)'     #Remove only spaces around name
  reNV='[ ]*([^ ]*)+[ ]*=[ ]*(.*)'  #Remove spaces around name and spaces before value
  if [[ $p =~ $reSec ]]; then
      section=${BASH_REMATCH[1]}
  elif [[ $p =~ $reNV ]]; then
    sNm=${section}_${BASH_REMATCH[1]}
    sVa=${BASH_REMATCH[2]}
    set -a
    eval "$(echo "$sNm"=\""$sVa"\")"
    set +a
  fi
done < $1

然后在另一个脚本中,我获得命令的结果,并可以使用其中的任何变量

test.sh

#!/bin/bash

source parseini test.ini

echo $section2_name2

最终从命令行输出是

# ./test.sh 
value_2

很好的解决方案!谢谢!
迈克尔

2

这是我的版本,该版本解析节并用它填充全局关联数组g_iniProperties。请注意,这仅适用于bash v4.2及更高版本。

function parseIniFile() { #accepts the name of the file to parse as argument ($1)
    #declare syntax below (-gA) only works with bash 4.2 and higher
    unset g_iniProperties
    declare -gA g_iniProperties
    currentSection=""
    while read -r line
    do
        if [[ $line = [*  ]] ; then
            if [[ $line = [* ]] ; then 
                currentSection=$(echo $line | sed -e 's/\r//g' | tr -d "[]")  
            fi
        else
            if [[ $line = *=*  ]] ; then
                cleanLine=$(echo $line | sed -e 's/\r//g')
                key=$currentSection.$(echo $cleanLine | awk -F: '{ st = index($0,"=");print  substr($0,0,st-1)}')
                value=$(echo $cleanLine | awk -F: '{ st = index($0,"=");print  substr($0,st+1)}')
                g_iniProperties[$key]=$value
            fi
        fi;
    done < $1
}

这是使用上述功能的示例代码:

parseIniFile "/path/to/myFile.ini"
for key in "${!g_iniProperties[@]}"; do
    echo "Found key/value $key = ${g_iniProperties[$key]}"
done

1

该脚本将获得如下参数:

表示如果您的ini具有:

pars_ini.ksh <ini文件的路径> <ini文件中扇区的名称> <名称中的名称=要返回的值>

例如。怎么称呼它:


[ 环境 ]

a = x

[DataBase_Sector]

DSN =某物


然后调用:

pars_ini.ksh /users/bubu_user/parameters.ini DataBase_Sector DSN

这将检索以下“内容”

脚本“ pars_ini.ksh”:

\#!/bin/ksh

\#INI_FILE=path/to/file.ini

\#INI_SECTION=TheSection

\# BEGIN parse-ini-file.sh

\# SET UP THE MINIMUM VARS FIRST

alias sed=/usr/local/bin/sed

INI_FILE=$1

INI_SECTION=$2

INI_NAME=$3

INI_VALUE=""


eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \

    -e 's/;.*$//' \

    -e 's/[[:space:]]*$//' \

    -e 's/^[[:space:]]*//' \

    -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \

   < $INI_FILE  \

    | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^;].*\=.*/p;}"`


TEMP_VALUE=`echo "$"$INI_NAME`

echo `eval echo $TEMP_VALUE`

1

我编写了一个快速简便的python脚本,将其包含在bash脚本中。

例如,您的ini文件被调用,food.ini 并且在文件中您可以包含一些部分和某些行:

[FRUIT]
Oranges = 14
Apples = 6

复制这个小的6行Python脚本并将其另存为 configparser.py

#!/usr/bin/python
import configparser
import sys
config = configparser.ConfigParser()
config.read(sys.argv[1])
print config.get(sys.argv[2],sys.argv[3])

现在,您可以在bash脚本中执行此操作。

OrangeQty=$(python configparser.py food.ini FRUIT Oranges)

要么

ApplesQty=$(python configparser.py food.ini FRUIT Apples)
echo $ApplesQty

前提是:

  1. 您已经安装了Python
  2. 您已经安装了configparser库(应该随std python安装一起提供)

希望能有所帮助 :¬)


我一直在寻找可以做到这一点的东西,所以我按照示例进行操作,效果很好。我忘了写这个!!!我试图为自己投票,但是,我不能为自己投票!!!哈哈
joe_evans 18'Apr 27'11

0

我的单线版

#!/bin/bash
#Reader for MS Windows 3.1 Ini-files
#Usage: inireader.sh

# e.g.: inireader.sh win.ini ERRORS DISABLE
# would return value "no" from the section of win.ini
#[ERRORS]
#DISABLE=no
INIFILE=$1
SECTION=$2
ITEM=$3
cat $INIFILE | sed -n /^\[$SECTION\]/,/^\[.*\]/p | grep "^[:space:]*$ITEM[:space:]*=" | sed s/.*=[:space:]*//

0

刚写完我自己的解析器。我尝试使用这里找到的各种解析器,似乎没有一个同时适用于ksh93(AIX)和bash(Linux)。

这是旧的编程风格-逐行解析。由于它使用了很少的外部命令,因此速度非常快。由于数组动态名称需要所有评估,所以速度稍慢。

ini支持3种特殊语法:

  • includefile = ini文件->加载一个附加的ini文件。将ini拆分为多个文件或重新使用某些配置很有用
  • includedir = directory->与includefile相同,但包含完整目录
  • includesection = section->将现有的部分复制到当前部分。

我使用所有这些语法来制作非常复杂,可重复使用的ini文件。在安装新OS时对安装产品很有用-我们做了很多。

可以使用$ {ini [$ section。$ item]}访问值。必须在调用此数组之前定义该数组。

玩得开心。希望对其他人有用!

function Show_Debug {
    [[ $DEBUG = YES ]] && echo "DEBUG $@"
    }

function Fatal {
    echo "$@. Script aborted"
    exit 2
    }
#-------------------------------------------------------------------------------
# This function load an ini file in the array "ini"
# The "ini" array must be defined in the calling program (typeset -A ini)
#
# It could be any array name, the default array name is "ini".
#
# There is heavy usage of "eval" since ksh and bash do not support
# reference variable. The name of the ini is passed as variable, and must
# be "eval" at run-time to work. Very specific syntax was used and must be
# understood before making any modifications.
#
# It complexify greatly the program, but add flexibility.
#-------------------------------------------------------------------------------

function Load_Ini {
    Show_Debug "$0($@)"
    typeset ini_file="$1"
# Name of the array to fill. By default, it's "ini"
    typeset ini_array_name="${2:-ini}"
    typeset section variable value line my_section file subsection value_array include_directory all_index index sections pre_parse
    typeset LF="
"
    if [[ ! -s $ini_file ]]; then
        Fatal "The ini file is empty or absent in $0 [$ini_file]"
    fi

    include_directory=$(dirname $ini_file)
    include_directory=${include_directory:-$(pwd)}

    Show_Debug "include_directory=$include_directory"

    section=""
# Since this code support both bash and ksh93, you cannot use
# the syntax "echo xyz|while read line". bash doesn't work like
# that.
# It forces the use of "<<<", introduced in bash and ksh93.

    Show_Debug "Reading file $ini_file and putting the results in array $ini_array_name"
    pre_parse="$(sed 's/^ *//g;s/#.*//g;s/ *$//g' <$ini_file | egrep -v '^$')"
    while read line; do
        if [[ ${line:0:1} = "[" ]]; then # Is the line starting with "["?
# Replace [section_name] to section_name by removing the first and last character
            section="${line:1}"
            section="${section%\]}"
            eval "sections=\${$ini_array_name[sections_list]}"
            sections="$sections${sections:+ }$section"
            eval "$ini_array_name[sections_list]=\"$sections\""
            Show_Debug "$ini_array_name[sections_list]=\"$sections\""
            eval "$ini_array_name[$section.exist]=YES"
            Show_Debug "$ini_array_name[$section.exist]='YES'"
        else
            variable=${line%%=*}   # content before the =
            value=${line#*=}       # content after the =

            if [[ $variable = includefile ]]; then
# Include a single file
                Load_Ini "$include_directory/$value" "$ini_array_name"
                continue
            elif [[ $variable = includedir ]]; then
# Include a directory
# If the value doesn't start with a /, add the calculated include_directory
                if [[ $value != /* ]]; then
                    value="$include_directory/$value"
                fi
# go thru each file
                for file in $(ls $value/*.ini 2>/dev/null); do
                    if [[ $file != *.ini ]]; then continue; fi
# Load a single file
                    Load_Ini "$file" "$ini_array_name"
                done
                continue
            elif [[ $variable = includesection ]]; then
# Copy an existing section into the current section
                eval "all_index=\"\${!$ini_array_name[@]}\""
# It's not necessarily fast. Need to go thru all the array
                for index in $all_index; do
# Only if it is the requested section
                    if [[ $index = $value.* ]]; then
# Evaluate the subsection [section.subsection] --> subsection
                        subsection=${index#*.}
# Get the current value (source section)
                        eval "value_array=\"\${$ini_array_name[$index]}\""
# Assign the value to the current section
# The $value_array must be resolved on the second pass of the eval, so make sure the
# first pass doesn't resolve it (\$value_array instead of $value_array).
# It must be evaluated on the second pass in case there is special character like $1,
# or ' or " in it (code).
                        eval "$ini_array_name[$section.$subsection]=\"\$value_array\""
                        Show_Debug "$ini_array_name[$section.$subsection]=\"$value_array\""
                    fi
                done
            fi

# Add the value to the array
            eval "current_value=\"\${$ini_array_name[$section.$variable]}\""
# If there's already something for this field, add it with the current
# content separated by a LF (line_feed)
            new_value="$current_value${current_value:+$LF}$value"
# Assign the content
# The $new_value must be resolved on the second pass of the eval, so make sure the
# first pass doesn't resolve it (\$new_value instead of $new_value).
# It must be evaluated on the second pass in case there is special character like $1,
# or ' or " in it (code).
            eval "$ini_array_name[$section.$variable]=\"\$new_value\""
            Show_Debug "$ini_array_name[$section.$variable]=\"$new_value\""
        fi
    done  <<< "$pre_parse"
    Show_Debug "exit $0($@)\n"
    }

0

此实现使用awk并具有以下优点:

  1. 只返回第一个匹配项
  2. 忽略以a开头的行 ;
  3. 修剪前导和尾随空白,但不修剪内部空白

格式化版本

awk -F '=' '/^\s*database_version\s*=/ {
            sub(/^ +/, "", $2);
            sub(/ +$/, "", $2);
            print $2;
            exit;
          }' parameters.ini

单线

awk -F '=' '/^\s*database_version\s*=/ { sub(/^ +/, "", $2); sub(/ +$/, "", $2); print $2; exit; }' parameters.ini

0

当我在base64中使用密码时,我放置了分隔符“:”,因为base64字符串可能具有“ =”。例如(我使用ksh):

> echo "Abc123" | base64
QWJjMTIzCg==

parameters.ini放线pass:QWJjMTIzCg==,最后:

> PASS=`awk -F":" '/pass/ {print $2 }' parameters.ini | base64 --decode`
> echo "$PASS"
Abc123

如果该行中有空格(如"pass : QWJjMTIzCg== "添加)| tr -d ' '以对其进行修剪:

> PASS=`awk -F":" '/pass/ {print $2 }' parameters.ini | tr -d ' ' | base64 --decode`
> echo "[$PASS]"
[Abc123]

0

这使用系统perl并清除正则表达式:

cat parameters.ini | perl -0777ne 'print "$1" if /\[\s*parameters\.ini\s*\][\s\S]*?\sdatabase_version\s*=\s*(.*)/'

0

除了其他答案,“ Karen Gabrielyan”的答案是最好的,但是在某些情况下我们没有awk,例如典型的busybox,我通过以下代码更改了答案。

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}


  function parseIniFile() { #accepts the name of the file to parse as argument ($1)
        #declare syntax below (-gA) only works with bash 4.2 and higher
        unset g_iniProperties
        declare -gA g_iniProperties
        currentSection=""
        while read -r line
        do
            if [[ $line = [*  ]] ; then
                if [[ $line = [* ]] ; then 
                    currentSection=$(echo $line | sed -e 's/\r//g' | tr -d "[]")  
                fi
            else
                if [[ $line = *=*  ]] ; then
                    cleanLine=$(echo $line | sed -e 's/\r//g')
                    key=$(trim $currentSection.$(echo $cleanLine | cut -d'=' -f1'))
                    value=$(trim $(echo $cleanLine | cut -d'=' -f2))
                    g_iniProperties[$key]=$value
                fi
            fi;
        done < $1
    }

我不确定awk丢失的可能性有多大,但是可以使用sed,cut和相对更高级的bash这样的语法。
Ondrej K.

大多数初始根文件系统将/ linuxrc或/ init作为shell脚本实现,因此包括最小的shell(通常为/ bin / ash)以及一些必要的用户空间实用程序
Ehsan Ahmadi

当然。我有点惊讶您不使用awk构建您的busybox,但是仍然具有sed,cut和对各种“ bashisms”的支持。并非不可能,只是让我感到奇怪。;)
Ondrej K.

其他工具比awk更轻巧。如果您在ubuntu发行版中使用initramfs-tools将脚本编写到initramfs中,则会发现您没有awk,并且其他工具(如sed,grep ...)的操作也很少。
Ehsan Ahmadi

当然,我不是在谈论GNU awk或其他全面的awk,只是想知道通过配置busybox不包括awk支持可以节省多少(特别是考虑到提到的其他位并未从该配置中删除)。* buntu initrd可能就是这样的。只是想知道所有的组合/选择。
Ondrej K.

0

如果Python可用,则以下内容将读取所有节,键和值,并将它们保存在名称中的变量中,格式为“ [section] _ [key]”。Python可以正确读取.ini文件,因此我们可以使用它。

#!/bin/bash

eval $(python3 << EOP
from configparser import SafeConfigParser

config = SafeConfigParser()
config.read("config.ini"))

for section in config.sections():
    for (key, val) in config.items(section):
        print(section + "_" + key + "=\"" + val + "\"")
EOP
)

echo "Environment_type:  ${Environment_type}"
echo "Environment_name:  ${Environment_name}"

config.ini

[Environment]
  type                = DEV
  name                = D01

0

您可以使用CSV解析器xsv来解析INI数据。

cargo install xsv
$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
$ xsv select -d "=" - <<< "$( cat /etc/*release )" | xsv search --no-headers --select 1 "DISTRIB_CODENAME" | xsv select 2
xenial

或来自文件。

$ xsv select -d "=" - file.ini | xsv search --no-headers --select 1 "DISTRIB_CODENAME" | xsv select 2

0

如果使用部分,则可以完成以下工作:

原始输出示例:

$ ./settings
[section]
SETTING_ONE=this is setting one
SETTING_TWO=This is the second setting
ANOTHER_SETTING=This is another setting

正则表达式解析:

$ ./settings | sed -n -E "/^\[.*\]/{s/\[(.*)\]/\1/;h;n;};/^[a-zA-Z]/{s/#.*//;G;s/([^ ]*) *= *(.*)\n(.*)/\3_\1='\2'/;p;}"
section_SETTING_ONE='this is setting one'
section_SETTING_TWO='This is the second setting'
section_ANOTHER_SETTING='This is another setting'

现在一起:

$ eval "$(./settings | sed -n -E "/^\[.*\]/{s/\[(.*)\]/\1/;h;n;};/^[a-zA-Z]/{s/#.*//;G;s/([^ ]*) *= *(.*)\n(.*)/\3_\1='\2'/;p;}")"
$ echo $section_SETTING_TWO
This is the second setting

0

我有很好的一行(assuimng你有phpjq安装):

cat file.ini | php -r "echo json_encode(parse_ini_string(file_get_contents('php://stdin'), true, INI_SCANNER_RAW));" | jq '.section.key'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.