Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I grab an INI value within a shell script?

People also ask

What is $@ in shell script?

$@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

What is $1 and $2 in shell script?

$0 is the name of the script itself (script.sh) $1 is the first argument (filename1) $2 is the second argument (dir1)


How about grepping for that line then using awk

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

You can use bash native parser to interpret ini values, by:

$ source <(grep = file.ini)

Sample file:

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

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

If you only want a single value just grep for it:

source <(grep var1 file.ini)

For the demo, check this recording at asciinema.

It is simple as you don't need for any external library to parse the data, but it comes with some disadvantages. For example:

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

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

    Or if you don't care about the 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
    
  • The sections aren't supported (e.g. if you've [section-name], then you've to filter it out as shown above, e.g. grep =), the same for other unexpected errors.

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

    E.g.

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

    Note: Where -A5 is the number of rows to read in the section. Replace source with cat to debug.

  • If you've got any parsing errors, ignore them by adding: 2>/dev/null

See also:

  • How to parse and convert ini file into bash array variables? at serverfault SE
  • Are there any tools for modifying INI style files from shell script

Sed one-liner, that takes sections 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. Run the following:

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

will give you

def

Bash does not provide a parser for these files. Obviously you can use an awk command or a couple of sed calls, but if you are bash-priest and don't want to use any other shell, then 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
}

Usage:

# 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 can be found at The Old School DevOps blog site.


Just include your .ini file into bash body:

File example.ini:

DBNAME=test
DBUSER=scott
DBPASSWORD=tiger

File example.sh

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

All of the solutions I've seen so far also hit on commented out lines. This one didn't, if the comment code is ;:

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

one of more possible solutions

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