How to get INI value in shell script?

I have a parameters.ini file, for example:

[parameters.ini] database_user = user database_version = 20110611142248 

I want to read and use the version of the database specified in the parameters.ini file from the bash shell so that I can process it.

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

How should I do it?

+83
bash shell ubuntu
Jun 11 2018-11-11T00:
source share
25 answers

How about grepping for this line and then awk

 version=$(awk -F "=" '/database_version/ {print $2}' parameters.ini) 
+73
Jun 11 '11 at 10:15
source share

You can use your own bash analyzer to interpret ini values:

 $ source <(grep = file.ini) 

Sample file:

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

To access the variables, you simply print them: echo $var1 . You can also use arrays as shown above ( echo ${IPS[@]} ).

If you only need one value, just enter grep:

 source <(grep var1 file.ini) 

It is simple because you do not need any external library for data analysis, but it has some disadvantages. For example:

  • If you have spaces between = (name and value of the variable), then you must trim the spaces first, e.g.

     $ source <(grep = file.ini | sed 's/ *= */=/g') 

    Or, if you do not need spaces (including in the middle), use:

     $ source <(grep = file.ini | tr -d ' ') 
  • To support ; comments, replace them with # :

     $ sed "s/;/#/g" foo.ini | source /dev/stdin 
  • Sections are not supported (for example, if you have a [section-name] , you must filter it as shown above, for example, grep = ), the same goes for other unexpected errors.

    If you need to read a specific value in a specific section, use grep -A , sed , awk or ex ).

    for example

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

    Note. Where -A5 is the number of lines to read in the section. Replace source with cat for debugging.

  • If you have parsing errors, ignore them by adding: 2>/dev/null

See Also: How to parse and convert an INI file into bash array variables? on the server SE

+37
Mar 01 '15 at 2:59
source share

Bash does not provide a parser for these files. Obviously, you can use the awk command or a couple of sed calls, but if you are bash-priest and don't want to use any other shell, you can try the following obscure code:

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

Using:

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

The Bash ini parser can be found on The Old School DevOps blog site .

+28
Jun 11 2018-11-11T00:
source share

Just include your .ini file in the bash body:

Example.ini file:

 DBNAME=test DBUSER=scott DBPASSWORD=tiger 

File example.sh

 #!/bin/bash #Including .ini file . example.ini #Test echo "${DBNAME} ${DBUSER} ${DBPASSWORD}" 
+19
May 08 '15 at 18:27
source share

Sed one-liner that takes partitions into account. Example file:

 [section1] param1=123 param2=345 param3=678 [section2] param1=abc param2=def param3=ghi [section3] param1=000 param2=111 param3=222 

Say you want param2 from section2. Follow these steps:

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

will provide you

 def 
+17
Nov 24 '16 at 4:26
source share

one of the possible solutions

 dbver=$(sed -n 's/.*database_version *= *\([^ ]*.*\)/\1/p' < parameters.ini) echo $dbver 
+11
Jun 11 '11 at 23:50
source share

All the solutions that I have seen so far also affect the commented lines. This was not if the comment code ; :

 awk -F '=' '{if (! ($0 ~ /^;/) && $0 ~ /database_version/) print $2}' file.ini 
+11
Jan 25 '13 at 18:14
source share

Display the my_key value in the my_file ini file:

 sed -n -e 's/^\s*my_key\s*=\s*//p' my_file 
  • -n - do not print anything by default
  • -e - execute expression
  • s/PATTERN//p - display something following this pattern In the pattern:
  • ^ - the pattern starts at the beginning of the line
  • \s - space character
  • * - zero or many (white space characters)

Example:

 $ 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:

Find a pattern in which the line starts with zero or many white space characters, followed by the string my_key, followed by zero or many white space characters, an equal sign, then zero or many white space characters. Show the rest of the contents of this line after this template.

+8
Sep 14 '14 at 14:11
source share

For people (like me) who want to read INI files from shell scripts (read shell, not bash), I have selected a small helper library that tries to do just that:

https://github.com/wallyhall/shini (MIT license, do as you please with it. I linked above, including its built-in, since the code is quite long.)

It is slightly more "complicated" than the simple sed lines suggested above, but they work on a very similar basis.

The function reads the file in a line - searches for section markers ( [section] ) and key / value declarations ( key=value ).

In the end, you get a callback to your own function - section, key and value.

+4
Sep 15 '14 at 19:51
source share

You can use the crudini tool to get ini values, for example:

 DATABASE_VERSION=$(crudini --get parameters.ini '' database_version) 
+3
Aug 26 '14 at 19:21
source share

SED

You can use sed to parse the ini configuration file, especially if you have section names such as:

 # 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 you can use the following sed in the script to analyze the data above:

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

this converts ini data to this flat format:

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

so it will be easier to parse using sed , awk or read , with section names on each line.

Authors and source: configuration files for shell scripts , Michael Grunewald




Alternatively, you can use this project: chilladx/config-parser , a configuration analyzer using sed .

+2
Jul 15 '16 at 10:15
source share

Some answers do not match the comments. Some do not respect sections. Some recognize only one syntax (only ":" or only "="). Some Python answers fail on my machine due to various captures or inability to import the sys module. Everything is a little too short for me.

So, I wrote my own, and if you have modern Python, you can probably call it from your Bash shell. It has the advantage of following some general Python coding rules, and even provides reasonable error messages and help. To use it, call it something like myconfig.py (don't call it configparser.py or it can try to import it yourself), make it executable and call it like

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

Here is my code for Python 3.5 on 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 __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
Aug 03 '17 at 21:30
source share

As with other Python answers, you can do this using the -c flag to execute a sequence of Python statements given on the command line:

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

The advantage of this is that only the standard Python library is required, and also that you do not need to write a separate script file.

Or use a document here for better readability, this way:

 #!/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
Sep 29 '17 at 20:38 on
source share

Here is my version that parses partitions and populates them with the g_iniProperties global associative array. Please note that this only works with bash v4.2 and higher.

 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 } 

And here is a sample code using the function above:

 parseIniFile "/path/to/myFile.ini" for key in "${!g_iniProperties[@]}"; do echo "Found key/value $key = ${g_iniProperties[$key]}" done 
+2
Dec 28 '17 at 20:28
source share

This script will receive the following parameters:

means if your ini has:

pars_ini.ksh <path to ini file> <sector name in Ini file> <name in name = return value>

eg. what to call him:




[Environment]

a = x

[DataBase_Sector]

DSN = something




Then call:

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

this will retrieve the next "something"

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
Feb 12 '13 at 15:06
source share

My single line version

 #!/bin/bash #Reader for MS Windows 3.1 Ini-files #Usage: inireader.sh # eg: 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
Sep 03 '15 at 11:45
source share

When I use the password in base64, I put the delimiter ":" because the base64 string can have "=". For example (I use ksh ):

 > echo "Abc123" | base64 QWJjMTIzCg== 

In parameters.ini put the line pass:QWJjMTIzCg== and finally:

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

If the string has spaces such as "pass : QWJjMTIzCg== " add | tr -d ' ' | tr -d ' ' to crop them:

 > PASS=`awk -F":" '/pass/ {print $2 }' parameters.ini | tr -d ' ' | base64 --decode` > echo "[$PASS]" [Abc123] 
0
Sep 10 '15 at 16:28
source share

Just finished writing my own parser. I tried using the different parser found here, but it doesn't seem to work with ksh93 (AIX) and bash (Linux).

The old programming style is parsing line by line. Pretty quickly, as he used several external commands. A bit slower due to all the eval requirements needed for a dynamic array name.

Ini supports 3 special syntaxes:

  • includefile = ini file -> Download an additional ini file. Useful for splitting ini in multiple files or reusing some part of the configuration.
  • includedir = directory -> Same as includefile but includes the full directory
  • includeection = section -> Copy an existing section into the current section.

I used all the thoses syntax to have a pretty complicated, reusable ini file. It is useful to install products when installing a new OS - we do this a lot.

Values ​​can be accessed using $ {ini [$ section. $ item]}. An array MUST be defined before calling this.

Enjoy. Hope this is helpful to someone else!

 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 "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 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 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
Mar 17 '16 at 2:05
source share

This implementation uses awk and has the following advantages:

  • Only the first matching record will return
  • Ignores lines starting with ;
  • Trimming leading and trailing spaces, but not inner spaces

Formatted Version :

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

Single liner

 awk -F '=' '/^\s*database_version\s*=/ { sub(/^ +/, "", $2); sub(/ +$/, "", $2); print $2; exit; }' parameters.ini 
0
Jun 23 '16 at 16:25
source share

I wrote a quick and simple python script to include in my bash script.

For example, your INI file is called food.ini and in this file you can have several sections and several lines:

 [FRUIT] Oranges = 14 Apples = 6 

Copy this small 6-line Python script and save it as 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]) 

Now, in your bash script you can do this, for example.

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

or

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

This implies:

  1. you have Python installed
  2. you have the configparser library installed (it should come with installing std python)

Hope this helps: ¬)

0
Sep 11 '16 at 17:15
source share

complex simplicity

ini file

test.ini

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

bash script with read and 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 

and then in another script I proceed from the results of the command and can use any variables inside

test.sh

 #!/bin/bash source parseini test.ini echo $section2_name2 

Finally, from the command line output in this way

 # ./test.sh value_2 
0
Nov 01 '17 at 3:01
source share

This uses system Perl and pure regular expressions:

 cat parameters.ini | perl -0777ne 'print "$1" if /\[\s*parameters\.ini\s*\][\s\S]*?\sdatabase_version\s*=\s*(.*)/' 
0
Jun 21 '18 at 1:06
source share

The answer "Karen Gabrielyan" among the other answers was the best, but in some environments we do not have awk, as in a typical busybox, I changed the answer using the code below.

 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
Sep 22 '18 at 12:19
source share

If Python is available, the following will read all sections, keys and values ​​and save them in variables with names in the format "[section] _ [key]". Python can read .ini files correctly, so we use it.

 #!/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
Feb 06 '19 at 19:49
source share

You can use the CSV xsv analyzer to analyze the INI data.

 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 

or from a file.

 $ xsv select -d "=" - file.ini | xsv search --no-headers --select 1 "DISTRIB_CODENAME" | xsv select 2 
0
Aug 21 '19 at 11:17
source share



All Articles