wake-up-neo.com

Wie greife ich ein? INI Wert innerhalb eines Shell-Skripts?

Ich habe eine parameters.ini-Datei wie:

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

Ich möchte die in der parameters.ini-Datei angegebene Datenbankversion aus einem Bash-Shell-Skript einlesen und verwenden, damit ich es verarbeiten kann.

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

Wie würde ich das machen?

73
Stephen Watkins

Wie wäre es mit einem Grepping für diese Zeile und dann mit awk

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

Sie können den bash-Parser verwenden, um die Ini-Werte zu interpretieren, indem Sie:

$ source <(grep = file.ini)

Beispieldatei:

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

Um auf Variablen zuzugreifen, drucken Sie sie einfach aus: echo $var1. Sie können auch Arrays wie oben gezeigt verwenden (echo ${IPS[@]}).

Wenn Sie nur einen einzelnen Wert haben möchten, greifen Sie einfach auf grep:

source <(grep var1 file.ini)

Es ist einfach, da Sie keine externe Bibliothek benötigen, um die Daten zu analysieren, aber es hat einige Nachteile. Zum Beispiel:

  • Wenn Sie Leerzeichen zwischen = (Variablenname und -wert) haben, müssen Sie zuerst die Leerzeichen entfernen, z.

    $ source <(grep = file.ini | sed 's/ *= */=/g')
    
  • Um ;-Kommentare zu unterstützen, ersetzen Sie sie durch #:

    $ sed "s/;/#/g" foo.ini | source /dev/stdin
    
  • Die Abschnitte werden nicht unterstützt (z. B. wenn Sie [section-name] haben, müssen Sie sie wie oben gezeigt herausfiltern, z. B. grep =). Dies gilt auch für andere unerwartete Fehler.

    Wenn Sie einen bestimmten Wert in einem bestimmten Abschnitt lesen müssen, verwenden Sie grep -A, sed, awk oder ex ).

    Z.B.

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

    Hinweis: Dabei ist -A5 die Anzahl der Zeilen, die im Abschnitt gelesen werden sollen. Ersetzen Sie source durch cat zum Debuggen.

  • Wenn Sie Fehler bei der Analyse haben, ignorieren Sie diese, indem Sie Folgendes hinzufügen: 2>/dev/null

Siehe auch: Wie kann ich eine INI-Datei in Bash-Array-Variablen analysieren und konvertieren? bei Serverfault SE

35
kenorb

Bash bietet keinen Parser für diese Dateien. Natürlich können Sie einen awk-Code oder ein paar sed-Aufrufe verwenden. Wenn Sie jedoch Bash-Priester sind und nichts mehr verwenden möchten, können Sie den folgenden Code verwenden:

#!/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 be =
    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
}

Verwendungszweck:

# 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 finden Sie auf The Old School DevOps Blog-Site .

27
Fredrik Pihl

Fügen Sie Ihre INI-Datei einfach in den Bash-Körper ein:

Datei example.ini :

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

Datei example.sh

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

Sed Einliner, der die Sektionen berücksichtigt. Beispieldatei:

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

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

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

Angenommen, Sie möchten param2 von section2. Führen Sie folgendes aus:

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

werde dir geben

def
13
egridasov

eine von mehreren möglichen Lösungen

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

Alle Lösungen, die ich bisher gesehen habe, sind auch auf kommentierte Zeilen eingegangen. Dies ist nicht der Fall, wenn der Kommentarcode ; lautet:

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

Zeigt den Wert von my_key in einem ini-style my_file an:

sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
  • -n - druckt nichts standardmäßig
  • -e - führe den Ausdruck aus
  • s/PATTERN//p - zeige alles an, das diesem Muster folgt.__Im Muster:
  • ^ - Muster beginnt am Zeilenanfang
  • \s - Leerzeichen
  • * - null oder viele (Leerzeichen)

Beispiel:

$ 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

So:

Suchen Sie nach einem Muster, bei dem die Zeile mit null oder vielen Leerzeichen (.__) beginnt. gefolgt von der Zeichenfolge my_key , gefolgt von null oder vielen Whitespace-Zeichen, einem Gleichheitszeichen und dann wieder null oder vielen Whitespace-Zeichen. Zeigen Sie den Rest des Inhalts in dieser Zeile nach diesem Muster an.

8
Dean Rather

Für Leute (wie ich), die INI -Dateien aus Shell-Skripten lesen (Shell lesen, nicht Bash) - Ich habe die kleine Hilfsbibliothek aufgeschlagen, die genau das versucht 

https://github.com/wallyhall/shini (MIT-Lizenz, machen Sie es wie Sie möchten. Ich habe oben verlinkt, einschließlich Inline, da der Code ziemlich lang ist.)

Es ist etwas "komplizierter" als die oben vorgeschlagenen einfachen sed-Zeilen - funktioniert aber auf einer sehr ähnlichen Basis.

Die Funktion liest Zeile für Zeile in eine Datei ein und sucht nach Abschnittsmarkierungen ([section]) und Schlüssel-/Wertdeklarationen (key=value).

Letztendlich erhalten Sie einen Rückruf auf Ihre eigene Funktion - Bereich, Schlüssel und Wert.

4
wally

Sie können das Werkzeug crudini verwenden, um Ini-Werte zu erhalten, z.

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

Einige Antworten respektieren keine Kommentare. Einige respektieren Abschnitte nicht. Einige erkennen nur eine Syntax (nur ":" oder nur "="). Einige Python-Antworten schlagen auf meinem Computer fehl, weil das Capture-System unterschiedlich ist oder das Sys-Modul nicht importiert wird. Alle sind mir etwas zu knapp.

Also habe ich mein eigenes geschrieben, und wenn Sie einen modernen Python haben, können Sie dies wahrscheinlich von Ihrer Bash-Shell aus aufrufen. Es hat den Vorteil, dass Sie einige der gängigen Python-Codierungskonventionen einhalten, und bietet sogar sinnvolle Fehlermeldungen und Hilfe. Um es zu benutzen, nennen Sie es etwas wie myconfig.py (nennen Sie es NICHT configparser.py oder es wird versucht, sich selbst zu importieren), machen Sie es ausführbar und nennen Sie es wie

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

Hier ist mein Code für Python 3.5 unter Linux:

#!/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 __== '__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
4dummies

Ähnlich wie die anderen Python-Antworten können Sie dies mit dem Flag -c ausführen, um eine Folge von Python-Anweisungen in der Befehlszeile auszuführen:

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

Dies hat den Vorteil, dass nur die Python-Standardbibliothek erforderlich ist, und der Vorteil, dass keine separate Skriptdatei geschrieben wird.

Oder verwenden Sie zur besseren Lesbarkeit ein Here-Dokument, also:

#!/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
2
argentpepper

Hier ist meine Version, die Abschnitte analysiert und ein globales assoziatives Array g_iniProperties damit belegt ..__ Beachten Sie, dass dies nur mit bash v4.2 und höher funktioniert.

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
}

Und hier ist ein Beispielcode, der die Funktion oben verwendet:

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

Sie können sed verwenden, um die ini-Konfigurationsdatei zu parsen, insbesondere wenn Sie Abschnittsnamen wie:

# 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

so können Sie das folgende sed-Skript verwenden, um die obigen Daten zu analysieren:

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

dadurch werden die INI-Daten in dieses flache Format konvertiert:

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

daher ist es einfacher, mit sed, awk oder read zu analysieren, indem in jeder Zeile Abschnittsnamen angegeben werden.

Quelle & Quelle: Konfigurationsdateien für Shell-Skripte , Michael Grünewald

2
kenorb

Dieses Skript erhält die folgenden Parameter:

was bedeutet, wenn Ihr Ini hat:

pars_ini.ksh <Pfad zur INI-Datei> <Name des Sektors in der INI-Datei> <Name in Name = zurückzugebender Wert>

z.B. wie man es nennt:


[ Umgebung ]

a = x

[DataBase_Sector]

DSN = etwas


Dann anrufen: 

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

dies wird das folgende "etwas" abrufen 

das Skript "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
jeo

Wenn ich ein Passwort in base64 verwende, setze ich das Trennzeichen ":", da die base64-Zeichenfolge möglicherweise "=" enthält. Zum Beispiel (ich verwende ksh):

> echo "Abc123" | base64
QWJjMTIzCg==

In parameters.ini setzen Sie die Zeile pass:QWJjMTIzCg== und schließlich:

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

Wenn die Zeile Leerzeichen wie "pass : QWJjMTIzCg== " enthält, fügen Sie | tr -d ' ' hinzu, um sie zu trimmen:

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

Ich habe ein schnelles und einfaches Python-Skript geschrieben, das in meinem Bash-Skript enthalten ist.

Zum Beispiel heißt Ihre Ini-Datei food.ini Und in der Datei können Sie einige Abschnitte und einige Zeilen haben:

[FRUIT]
Oranges = 14
Apples = 6

Kopieren Sie dieses kleine 6-Zeilen-Python-Skript und speichern Sie es als configparser.py.

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

Jetzt können Sie dies in Ihrem Bash-Skript zum Beispiel tun.

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

oder

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

Dies macht voraus: 

  1. sie haben Python installiert 
  2. sie haben die Configparser-Bibliothek installiert (dies sollte mit einer std-Python-Installation geliefert werden)

Hoffe es hilft: ¬)

0
joe_evans

Die Antwort von "Karen Gabrielyan" unter den anderen Antworten war die beste, aber in einigen Umgebungen haben wir keine Ahnung, wie bei einer typischen busybox. Ich habe die Antwort mit dem folgenden Code geändert.

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
    }
0
Ehsan Ahmadi

Dies verwendet das System Perl und bereinigt reguläre Ausdrücke: 

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

Sie können einen CSV-Parser xsv zum Parsen von INI Daten verwenden.

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

oder aus einer Datei.

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

komplexe Einfachheit 

ini-Datei

test.ini

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

bash-Skript mit Lesen und Ausführen

/ 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

in einem anderen Skript beziehe ich dann die Ergebnisse des Befehls und kann beliebige Variablen verwenden

test.sh

#!/bin/bash

source parseini test.ini

echo $section2_name2

endlich von der Kommandozeile aus die Ausgabe also

# ./test.sh 
value_2
0
The Lazy Coder

Meine Version des Einliners

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

Wenn Python verfügbar ist, werden im Folgenden alle Abschnitte, Schlüssel und Werte gelesen und in Variablen mit ihren Namen im Format "[section] _ [key]" gespeichert. Python kann .ini-Dateien richtig lesen, daher machen wir davon Gebrauch.

#!/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
Hans Deragon

Ich habe gerade meinen eigenen Parser geschrieben. Ich habe versucht, verschiedene Parser zu verwenden, die hier gefunden wurden, keiner scheint mit ksh93 (AIX) und bash (Linux) zu funktionieren.

Es ist ein alter Programmierstil, der Zeile für Zeile analysiert wird. Ziemlich schnell, da nur wenige externe Befehle verwendet wurden. Etwas langsamer, da alle Bewertungen für den dynamischen Namen des Arrays erforderlich sind.

Das ini unterstützt 3 spezielle Syntax:

  • includeefile = ini-Datei -> Lädt eine zusätzliche INI-Datei. Nützlich zum Aufteilen von ini in mehrere Dateien oder zur erneuten Verwendung eines Teils der Konfiguration
  • includedir = directory -> Entspricht dem Include-File, enthält jedoch ein vollständiges Verzeichnis
  • includeection = section -> Kopieren Sie einen vorhandenen Abschnitt in den aktuellen Abschnitt.

Ich habe alle diese Syntax verwendet, um eine ziemlich komplexe, wiederverwendbare Ini-Datei zu haben. Nützlich, um Produkte zu installieren, wenn ein neues Betriebssystem installiert wird - das machen wir oft.

Auf Werte kann mit $ {ini [$ section. $ Item]} zugegriffen werden. Das Array MUSS vor dem Aufruf definiert werden.

Habe Spaß. Hoffe, es ist nützlich für jemanden!

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

function Fatal {
    echo "[email protected] 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([email protected])"
    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([email protected])\n"
    }
0
user3637822

Diese Implementierung verwendet awk und hat folgende Vorteile:

  1. Gibt nur den ersten passenden Eintrag zurück
  2. Ignoriert Zeilen, die mit einem ; beginnen
  3. Schneidet führende und nachfolgende Leerzeichen, aber keine inneren Leerzeichen

Formatierte Version :

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

Einzeiler :

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