137 votes

Comment saisir une valeur INI dans un script shell script ?

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

[parameters.ini]
    database_user    = user
    database_version = 20110611142248

Je veux lire et utiliser la version de la base de données spécifiée dans le fichier parameters.ini à partir d'un shell bash script pour 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 dois-je m'y prendre ?

6 votes

Est-ce que l'une de ces réponses respecte les sections ?

0 votes

Notez que tout script qui commence par #!/bin/sh est un script POSIX sh, et non un script bash. C'est une distinction importante, car sh ne dispose pas de fonctionnalités comme les tableaux et les cartes (que bash appelle "tableaux associatifs") qui sont très utiles pour construire ce genre de choses.

8voto

kenorb Points 2464

sed

Vous pouvez utiliser sed pour analyser le fichier de configuration ini, surtout lorsque vous avez des noms de sections comme :

# 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 ce qui suit sed script 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
}

ceci 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

afin qu'il soit plus facile de l'analyser à l'aide de sed , awk o read en ayant des noms de sections dans chaque ligne.

Crédits et source : Fichiers de configuration pour les scripts. Michael Grünewald


Vous pouvez également utiliser ce projet : chilladx/config-parser un analyseur de configuration utilisant sed .

5voto

wally Points 411

Pour les personnes (comme moi) qui cherchent à lire des fichiers INI à partir de scripts shell scripts (lire shell, pas bash) - j'ai mis au point une petite bibliothèque d'aide qui essaie de faire exactement cela :

https://github.com/wallyhall/shini (Licence MIT, faites-en ce que vous voulez. J'ai fait le lien ci-dessus en l'incluant en ligne car le code est assez long).

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

La fonction lit un fichier ligne par ligne - en recherchant les marqueurs de section ( [section] ) et les déclarations clés/valeurs ( key=value ).

Au final, vous obtenez un rappel vers votre propre fonction - section, clé et valeur.

4voto

Voici ma version, qui analyse les sections et remplit un tableau associatif global. g_iniProperties avec elle. Notez que cela ne fonctionne qu'avec bash v4.2 et plus.

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

4voto

Juarez Rudsatz Points 101

Encore une autre mise en œuvre utilisant awk avec un peu plus de flexibilité.

function parse_ini() {
  cat /dev/stdin | awk -v section="$1" -v key="$2" '
    BEGIN {
      if (length(key) > 0) { params=2 }
      else if (length(section) > 0) { params=1 }
      else { params=0 }
    }
    match($0,/#/) { next }
    match($0,/^\[(.+)\]$/){
      current=substr($0, RSTART+1, RLENGTH-2)
      found=current==section
      if (params==0) { print current }
    }
    match($0,/(.+)=(.+)/) {
       if (found) {
         if (params==2 && key==$1) { print $3 }
         if (params==1) { printf "%s=%s\n",$1,$3 }
       }
    }'
}

Vous pouvez utiliser l'appel en passant entre 0 et 2 paramètres :

cat myfile1.ini myfile2.ini | parse_ini # List section names

cat myfile1.ini myfile2.ini | parse_ini 'my-section' # Prints keys and values from a section

cat myfile1.ini myfile2.ini | parse_ini 'my-section' 'my-key' # Print a single value

3voto

Volure DarkAngel Points 5916

Simplicité complexe

fichier ini

test.ini

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

bash script avec lecture et exécution

/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 je peux utiliser n'importe quelles variables dans

test.sh

#!/bin/bash

source parseini test.ini

echo $section2_name2

Enfin, en ligne de commande, la sortie est la suivante

# ./test.sh 
value_2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X