シェルスクリプト内でINI値を取得するにはどうすればよいですか?


97

私はparameters.iniファイルを持っています:

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

処理できるように、bashシェルスクリプト内から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 2017

回答:


83

その行をgreppingしてからawkを使用するのはどうですか

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

6
これには、「=」の後にスペースが含まれます。

10
スペースをトリミングするに| tr -d ' 'は、最後に追加します。
kenorb 2015

22
これは本当に良い解決策ではありません。2つの[parameters.ini]セクションがあり、それぞれに 'database_version'変数があるとします。その後、値を2回取得します。
nerdoc

4
はい、上記で処理されない多くのエッジケースがあるため、crudiniのような特殊なiniパーサーを検討してください
pixelbeat

3
基本的なiniファイルに対しては、まだ便利で迅速です。
Cyril N.

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 -Asedawkまたはex)。

    例えば

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

    注:-A5は、セクションで読み取る行数です。元に戻しsourcecatデバッグします。

  • 解析エラーが発生した場合は、以下を追加して無視してください。 2>/dev/null

以下も参照してください。


1
しかし... source <(grep = <(grep -A5 '\[section-b\]' file.ini))これは機能しません:[秒a] a = 1 b = 2 c = 3 [秒b] a = 2 b = 3 [秒c] a = 0。線による明確なルールがない場合
精神分裂病

ソースを使用しようとしましたが、$ var1をエコーすると何も返されません。どうして?
A. Gh

@ A.Ghよくわかりませんが、うまくいきます。Bashシェルを使用していることを確認してください。参照:asciinema.org/a/306481
ケノーブ

これは洗練されていたはずですが、OS X(Catalina)で機能させることができませんでした。zsh(現在のデフォルトシェル)のコマンドプロンプトから機能しますが、スクリプトに挿入するとエラーが発生しますsyntax error near unexpected token '('。bashを使用すると、プロンプトとスクリプトの両方から静かに失敗します。
MiRin

29

Bashはこれらのファイルのパーサーを提供していません。明らかにawkコマンドまたはいくつかのsed呼び出しを使用できますが、bash-priestで他のシェルを使用したくない場合は、次のあいまいなコードを試すことができます。

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

Bash ini-parserは、The Old School DevOpsブログサイトにあります。


3
このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。
alecxe 2013年

8
私は通常、このようなコメントをする人です。私が言えることは、私が若くて愚かだったということだけです:-)
Fredrik Pihl 2013年

1
このスニペットが気に入った場合は、github.com / albfan / bash
ini

3
正しく機能させるには、cfg.parserの代わりにcfg_parserを使用する必要があります
Wes

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

セクション2の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スタイルファイルのコメントなし。パラメータが1つだけ必要な場合は、paramnameのgrepを実行します。
gaoithe

次の行を読み取るよりもsed範囲アドレスを使用する方が良い:"/^\[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で動作し、フォールトトレラントです(内部に空の行があるファイル)。ありがとう
Anthony

17
INIファイルの[セクション]部分を処理しません。
Setop

これが最良の答えです!
JavaSheriff 2018年

17
うまくいけば、誰も「rm -rf /」をiniファイルに追加しない:(
HeyMan

1
サブシェルではるかに安全:$(。example.ini; echo $ DBNAME)
Rich Remer

13

これまでに見てきたすべてのソリューションは、コメントアウトされた行にもヒットしました。これは、コメントコードが;次の場合は、しませんでした:

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

2
a)コメントアウトされた行を処理するb)単純な:)
Sudar

1
@PenguinLustさん、これは素晴らしいです!使用法:1.セミコロンのプレフィックス付きで許可されるフルラインコメント(インラインの行末コメントは許可されません); 2.空白は結果から除外されません(したがって、iniファイルに「a = 1」がある場合、スクリプトの「a」の検索は「1」と評価されます)。
AnneTheAgile 14

1
スペースをトリミングするに| tr -d ' 'は、最後に追加します。
kenorb 2015

これには、推奨される回答と同じ問題があります。「database_version」のすべてのインスタンスを検索します
Nubcake

12

可能な解決策の1つ

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

8

my_keyの値をiniスタイルのmy_fileで表示します。

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 2015

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

したがってsed、を使用するawkread、すべての行にセクション名を含めると、解析が容易になります。

クレジットとソース:シェルスクリプトの設定ファイル、 MichaelGrünewald


または、次のプロジェクトを使用することもできます:chilladx/config-parser、を使用する構成パーサーsed


これは素晴らしい!そのように平らにすることを考えていましたが、これは私が一緒にハッキングしようとしていたことをはるかに超えています!
18年

6

crudiniツールを使用してini値を取得できます。例:

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

Pythonに基づいているため、組み込みLinuxアプリケーションなどには適さない場合があります。
Craig McQueen、

これは、Fedoraの標準リポジトリ(31でテスト済み)の一部です。 yum install crudini
じゃじゃ馬

5

シェルスクリプト(bashではなくシェルを読み取る)からINIファイルを読みたい人(私のような)のために-私はそれを正確に実行しようとする小さなヘルパーライブラリをノックアップしました:

https://github.com/wallyhall/shini(MITライセンス、好きなように使用してください。コードが非常に長いため、これをインラインで含めて上にリンクしました。)

これは、sed上で提案した単純な行よりも「複雑」ですが、非常によく似ています。

関数はファイルを1行ずつ読み取り、セクションマーカー([section])とキー/値の宣言(key=value)を探します。

最終的には、セクション、キー、値など、独自の関数へのコールバックを取得します。


@CraigMcQueen-今夜、非常にアルファ品質の書き込みサポートを追加しました。想像力を伸ばしても「完全」ではありません。
2015年

鮮やかさ!:-)メジャー
ジョナサン

5

他のPythonの回答と同様に、これを行うには、-cフラグを使用して、コマンドラインで指定された一連のPythonステートメントを実行します。

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

これには、Python標準ライブラリのみを必要とするという利点と、個別のスクリプトファイルを作成しないという利点があります。

または、ヒアドキュメントを使用して読みやすくします。

#!/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、

2

一部の回答はコメントを尊重していません。セクションを尊重しない人もいます。一部の構文は1つだけを認識します( ":"のみまたは "="のみ)。大文字と小文字が異なるか、sysモジュールのインポートに失敗したため、一部のPythonの回答が私のマシンで失敗します。すべてが私には少し簡潔すぎる。

だから私は自分で書いたのですが、もしあなたが最新のPythonを持っているなら、おそらくBashシェルからこれを呼び出すことができます。いくつかの一般的な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ファイル内のセクターの名前> <name = value内の名前>

例えば。それを呼び出す方法:


【環境】

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

私はbashスクリプトに含めるための迅速で簡単なpythonスクリプトを作成しました。

たとえば、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

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)の両方で動作するものはないようです。

これは古いプログラミングスタイルで、1行ずつ解析します。外部コマンドをほとんど使用しないため、かなり高速です。配列の動的な名前に必要なすべての評価のため、少し遅くなります。

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. で始まる行を無視します ;
  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

他の回答の中で「カレンガブリエリアン」の回答が最良でしたが、一部の環境では、典型的なbusyboxなどのawkがないため、以下のコードで回答を変更しました。

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を実装しているため、最小限のシェル(通常は/ bin / ash)といくつかの重要なユーザースペースユーティリティが含まれています
Ehsan Ahmadi

承知しました。awkを使用せずにbusyboxを構築したが、それでもsed、cut、およびさまざまな「バシズム」をサポートしていることに少し驚いています。それは不可能だというわけではなく、ただ不思議に思います。;)
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

INIデータの解析には、CSVパーサーxsvを使用できます。

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

私は素敵なワンライナーを持っています(あなたが持っているphpjqインストールされていると思います):

cat file.ini | php -r "echo json_encode(parse_ini_string(file_get_contents('php://stdin'), true, INI_SCANNER_RAW));" | jq '.section.key'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.