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.

0voto

Luis Hernandez Points 109

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==

Sur parameters.ini mettre 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 comme "pass : QWJjMTIzCg== " ajouter | tr -d ' ' pour les tailler :

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

0voto

user3637822 Points 21

Je viens de finir d'écrire mon propre analyseur syntaxique. J'ai essayé d'utiliser divers parseurs 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 utilise peu de commandes externes. Un peu plus lent à cause de toutes les évaluations nécessaires pour le nom dynamique du tableau.

L'ini supporte 3 syntaxes spéciales :

  • includefile=fichierini --> Charge un fichier ini additionnel. Utile pour diviser l'ini en plusieurs fichiers, ou réutiliser une partie de la configuration.
  • includedir=répertoire --> Identique à includefile, mais inclut un répertoire complet
  • includesection=section --> Copie une section existante dans la section courante.

J'ai utilisé toutes ces syntaxes pour avoir un fichier ini assez complexe et réutilisable. Utile pour installer des produits lors de l'installation d'un nouvel OS - nous le faisons souvent.

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

Amusez-vous bien. J'espère que cela sera utile à 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"
    }

0voto

Cela utilise le système perl et les expressions régulières propres :

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

0voto

Ehsan Ahmadi Points 4

La réponse de "Karen Gabrielyan" parmi d'autres réponses était la meilleure mais dans certains environnements nous n'avons pas awk, comme le busybox typique, j'ai changé la réponse par le code ci-dessous.

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
    }

0voto

Hans Deragon Points 162

Si Python est disponible, la commande suivante lira toutes les sections, clés et valeurs et les enregistrera dans des variables dont les noms suivront le format "[section]_[clé]". Python peut lire correctement les fichiers .ini, nous l'utilisons donc.

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

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