web-dev-qa-db-fra.com

Comment puis-je prendre un INI valeur dans un script shell?

J'ai un fichier parameters.ini, tel que:

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

Je souhaite lire et utiliser la version de la base de données spécifiée dans le fichier parameters.ini à partir d'un script shell bash afin de pouvoir la traiter .

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

Comment je ferais ça?

73
Stephen Watkins

Que diriez-vous de grepping pour cette ligne puis en utilisant awk

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

Vous pouvez utiliser l'analyseur natif bash pour interpréter les valeurs ini, par:

$ source <(grep = file.ini)

Exemple de fichier:

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

Pour accéder aux variables, il vous suffit de les imprimer: echo $var1. Vous pouvez également utiliser des tableaux comme indiqué ci-dessus (echo ${IPS[@]}).

Si vous voulez seulement une valeur unique, grep pour cela:

source <(grep var1 file.ini)

C'est simple, vous n'avez besoin d'aucune bibliothèque externe pour analyser les données, mais cela présente certains inconvénients. Par exemple:

  • Si vous avez des espaces entre = (nom et valeur de la variable), vous devez d’abord les rogner, par exemple.

    $ source <(grep = file.ini | sed 's/ *= */=/g')
    
  • Pour prendre en charge les commentaires ;, remplacez-les par #:

    $ sed "s/;/#/g" foo.ini | source /dev/stdin
    
  • Les sections ne sont pas prises en charge (par exemple, si vous avez [section-name], alors vous devez le filtrer comme indiqué ci-dessus, par exemple grep =), de même pour les autres erreurs inattendues.

    Si vous devez lire une valeur spécifique dans une section spécifique, utilisez grep -A, sed, awk ou ex ).

    Par exemple.

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

    Remarque: Où -A5 est le nombre de lignes à lire dans la section. Remplacez source par cat pour déboguer.

  • Si vous avez des erreurs d'analyse, ignorez-les en ajoutant: 2>/dev/null

Voir aussi: Comment analyser et convertir un fichier ini en variables de tableau bash? at serverfault SE

35
kenorb

Bash ne fournit pas d'analyseur syntaxique pour ces fichiers, vous pouvez évidemment utiliser un code awk ou quelques appels sed, mais si vous êtes bash-priest et ne voulez plus rien utiliser, vous pouvez essayer le code obscur suivant:

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

Utilisation:

# 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 peut être trouvé à Le site de blog Old School DevOps .

27
Fredrik Pihl

Incluez simplement votre fichier .ini dans le corps de bash:

Fichier exemple.ini :

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

Fichier exemple.sh

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

Sed one-liner, qui prend en compte les sections. Exemple de fichier:

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

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

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

Dites que vous voulez param2 de la section2. Exécutez ce qui suit:

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

te donnera

def
13
egridasov

une des solutions les plus possibles

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

Toutes les solutions que j'ai vues jusqu'à présent ont également été commentées. Celui-ci ne l'a pas été, si le code de commentaire est ;:

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

Affichez la valeur de my_key dans un style ini my_file :

sed -n -e 's/^\s*my_key\s*=\s*//p' my_file
  • -n - n'imprime rien par défaut
  • -e - exécute l'expression
  • s/PATTERN//p - affiche tout ce qui suit ce modèleDans le modèle:
  • ^ - le motif commence au début de la ligne
  • \s - caractère d'espacement
  • * - zéro ou plusieurs (caractères d'espacement)

Exemple:

$ 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

Alors:

Recherchez un modèle dont la ligne commence par zéro ou par plusieurs caractères d'espacement, suivi de la chaîne my_key , suivi de zéro ou de plusieurs caractères d'espacement, d'un signe égal, puis de nouveau de zéro ou de nombreux caractères d'espacement. Affichez le reste du contenu sur cette ligne en suivant ce modèle.

8
Dean Rather

Pour les personnes (comme moi) qui cherchent à lire INI des fichiers à partir de scripts Shell (lisez Shell, pas bash) - j'ai créé la petite bibliothèque d'aide qui tente de faire exactement cela: 

https://github.com/wallyhall/shini (Licence MIT, faites-la comme bon vous semble. J'ai mis un lien ci-dessus en l'incluant inline car le code est assez long.)

C'est un peu plus "compliqué" que les simples lignes sed suggérées ci-dessus - mais fonctionne sur une base très similaire.

La fonction lit dans un fichier ligne par ligne - recherche des marqueurs de section ([section]) et des déclarations clé/valeur (key=value).

En fin de compte, vous obtenez un rappel vers votre propre fonction - section, clé et valeur.

4
wally

Vous pouvez utiliser crudini tool pour obtenir les valeurs ini, par exemple:

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

Certaines réponses ne respectent pas les commentaires. Certains ne respectent pas les sections. Certains ne reconnaissent qu'une seule syntaxe (seulement ":" ou seulement "="). Certaines réponses Python échouent sur ma machine à cause d'une captialisation différente ou de l'impossibilité d'importer le module sys. Tous sont un peu trop laconiques pour moi.

J'ai donc écrit le mien et si vous avez un Python moderne, vous pouvez probablement appeler cela depuis votre shell Bash. Il présente l'avantage de respecter certaines des conventions de codage Python les plus courantes et fournit même des messages d'erreur sensibles et une aide. Pour l’utiliser, nommez-le comme myconfig.py (ne l’appelez PAS configparser.py ou essayez de l’importer lui-même), rendez-le exécutable et appelez-le

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

Voici mon code pour Python 3.5 sur 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

Comme pour les autres réponses Python, vous pouvez utiliser l’indicateur -c pour exécuter une séquence d’instructions Python figurant sur la ligne de commande:

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

Cela présente l'avantage de ne nécessiter que la bibliothèque standard Python et de ne pas écrire un fichier de script séparé.

Ou utilisez un document ici pour une meilleure lisibilité, ainsi:

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

Voici ma version, qui analyse les sections et remplit un tableau associatif global g_iniProperties with it . Notez que cela ne fonctionne qu'avec bash v4.2 et versions ultérieures.

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
}

Et voici un exemple de code utilisant la fonction ci-dessus:

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

Vous pouvez utiliser sed pour analyser le fichier de configuration ini, en particulier lorsque vous avez des noms de section tels que:

# 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

vous pouvez donc utiliser le script sed suivant pour analyser les données ci-dessus:

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

cela convertira les données ini dans ce format plat:

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

il sera donc plus facile d'analyser avec sed, awk ou read en ayant des noms de section dans chaque ligne.

Credits & source: Fichiers de configuration pour scripts Shell , Michael Grünewald

2
kenorb

Ce script va obtenir les paramètres suivants:

ce qui signifie que si votre ini a:

pars_ini.ksh <chemin du fichier ini> <nom du secteur dans le fichier Ini> <nom du nom = valeur à renvoyer>

par exemple. comment l'appeler:


[environnement]

a = x

[DataBase_Sector]

DSN = quelque chose


Puis en appelant: 

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

cela va récupérer le "quelque chose" suivant 

le script "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

Lorsque j'utilise un mot de passe en base64, je mets le séparateur ":" car la chaîne en base64 peut avoir "=". Par exemple (j'utilise ksh):

> echo "Abc123" | base64
QWJjMTIzCg==

Dans parameters.ini, mettez la ligne pass:QWJjMTIzCg== et, enfin:

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

Si la ligne comporte des espaces tels que "pass : QWJjMTIzCg== ", ajoutez | tr -d ' ' pour les rogner:

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

J'ai écrit un script python rapide et facile à inclure dans mon script bash.

Par exemple, votre fichier ini s'appelle food.ini Dans le fichier, vous pouvez avoir des sections et des lignes:

[FRUIT]
Oranges = 14
Apples = 6

Copiez ce petit script Python de 6 lignes et enregistrez-le sous le nom 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])

Maintenant, dans votre script bash, vous pouvez le faire par exemple.

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

ou

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

Cela prépare: 

  1. vous avez installé Python 
  2. vous avez la bibliothèque configparser installée (cela devrait venir avec une installation std python)

J'espère que ça vous aidera: ¬)

0
joe_evans

La réponse de "Karen Gabrielyan", entre autres réponses, était la meilleure, mais dans certains environnements, nous n’avons pas 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
    }
0
Ehsan Ahmadi

Cela utilise le système Perl et les expressions rationnelles propres: 

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

Vous pouvez utiliser un analyseur CSV xsv pour analyser les données 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

ou à partir d'un fichier.

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

simplicité complexe 

fichier ini

test.ini

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

script bash avec read et execute

/ 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

puis dans un autre script je source les résultats de la commande et peut utiliser des variables dans

test.sh

#!/bin/bash

source parseini test.ini

echo $section2_name2

enfin de ligne de commande, la sortie est donc

# ./test.sh 
value_2
0
The Lazy Coder

Ma version du one-liner

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

Si Python est disponible, les éléments suivants liront toutes les sections, clés et valeurs et les enregistreront dans des variables dont le nom correspond au format "[section] _ [clé]". Python peut lire les fichiers .ini correctement, nous nous en servons.

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

Vient de finir d'écrire mon propre analyseur. J'ai essayé d'utiliser divers analyseurs trouvés ici, aucun ne semble fonctionner à la fois avec ksh93 (AIX) et bash (Linux).

C'est un vieux style de programmation - analyser ligne par ligne. Assez rapide car il utilisait peu de commandes externes. Un peu plus lent en raison de toutes les évaluations requises pour le nom dynamique du tableau.

L'ini supporte 3 syntaxes spéciales:

  • includefile = fichier ini -> Chargez un fichier ini supplémentaire. Utile pour diviser des ini en plusieurs fichiers ou pour réutiliser une partie de la configuration
  • includedir = répertoire -> Identique à includefile, mais inclure un répertoire complet
  • includesection = section -> Copier une section existante dans la section en cours.

J'ai utilisé toute cette syntaxe pour avoir un fichier ini assez complexe et réutilisable. Utile pour installer des produits lors de l'installation d'un nouveau système d'exploitation - nous le faisons souvent.

Les valeurs sont accessibles avec $ {ini [$ section. $ Item]}. Le tableau DOIT être défini avant d'appeler cela.

S'amuser. J'espère que c'est utile pour quelqu'un d'autre!

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
user3637822

Cette implémentation utilise awk et présente les avantages suivants:

  1. Renvoie uniquement la première entrée correspondante
  2. Ignore les lignes qui commencent par un ;
  3. Limite les espaces de début et de fin, mais pas les espaces internes

Version formatée :

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

Bon mot :

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