Acessibilidade variável por seção do arquivo de configuração

0

Eu tenho um arquivo de configuração com dados seccionais, como mencionado abaixo. Usando o script de shell acessando cada variável. Estou usando o comando sed para isso, agora estou enfrentando um problema como se eu esquecesse de configurar uma variável exemplo: nome [APP1] ele levaria o nome [APP2].
Arquivo de Configuração:

[APP1]
name=Application1
StatusScript=/home/status_APP1.sh
startScript=/home/start_APP1.sh
stopScript=/home/stop_APP1.sh
restartScript=/home/restart.APP1.sh

[APP2]
name=Application2
StatusScript=/home/status_APP2.sh
startScript=/home/start_APP2.sh
stopScript=/home/stop_APP2.sh
restartScript=/home/restart.APP2.sh
logdir=/log/APP2/
.
.
.
.
.
[APPN]
name=ApplicationN
StatusScript=/home/status_APPN.sh
startScript=/home/start_APPN.sh
stopScript=/home/stop_APPN.sh
restartScript=/home/restart.APPN.sh
logdir=/log/APPN

comando shell usando:

sed -nr "/^\[APP1\]/ { :l /^name[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}"

Existe alguma maneira de resolver este problema, se alguma variável não configurada em uma seção é através de null ou 0 como valor da variável.

    
por Arun Binoy 17.05.2018 / 08:53

2 respostas

1

Você pode criar uma função de shell como esta:

printSection()
{
  section="$1"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    echo "$line"
  done
}

Você pode usar printSection como um comando e passar a seção como um parâmetro como:

printSection APP2

Para obter seu parâmetro, você pode usar um sed mais simples agora, como:

printSection APP2 | sed -n 's/^name=//p'

Isto estará operando em stdin e escrevendo para stdout. Então, se o seu arquivo de configuração de exemplo foi chamado de /etc/application.conf, e você quisesse armazenar o nome de APP2 em uma variável app2name, você poderia escrever isto:

app2name=$(printSection APP2 | sed -n 's/^name//p/' < /etc/applications.conf)

Ou você poderia criar a parte do parâmetro na função e ignorar o sed por completo, assim:

printValue()
{
  section="$1"
  param="$2"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    [[ "${line%=*}" == "$param" ]] && { echo "${line#*=}"; break; }
  done
}

Então você atribui seu var assim:

app2name=$(printValue APP2 name < /etc/applications.conf)
    
por 19.05.2018 / 01:01
1

Analise sua configuração em um formato não ambíguo e leia-a em um array associativo em uma versão recente de bash :

awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf

Isso encontra todos os cabeçalhos de seção e define o awk variable app para o conteúdo deles. Em seguida, ele prefixará cada linha seguinte com esse valor seguido por um ponto.

Isso criaria saída como

APP1.name=Application1
APP1.StatusScript=/home/status_APP1.sh
APP1.startScript=/home/start_APP1.sh
APP1.stopScript=/home/stop_APP1.sh
APP1.restartScript=/home/restart.APP1.sh
APP2.name=Application2
APP2.StatusScript=/home/status_APP2.sh
APP2.startScript=/home/start_APP2.sh
APP2.stopScript=/home/stop_APP2.sh
APP2.restartScript=/home/restart.APP2.sh
APP2.logdir=/log/APP2/

Se sua APP2 não tiver uma subseção name , a linha APP2.name não será exibida.

Em seguida, leia isso em uma matriz associativa em bash :

declare -A conf
while IFS='=' read -r key value; do
    conf[$key]="$value"
done < <(awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf)

Você pode agora consultar a variável conf para sua configuração:

printf 'The stopScript for APPN is "%s"\n' "${conf[APPN.stopScript]}"

Isso retornará

The stopScript for APPN is "/home/stop_APPN.sh"

Consultar um valor não existente produzirá uma string vazia.

O comando awk também pode ser substituído pelo seguinte comando sed :

sed -n \
    -e '/^\[/{s/[][]//g;h;}' \
    -e '/=/{H;g;s/\n/./;p;s/\..*//;h;}' file.conf

Expandido e anotado:

/^\[/{          # handle section headers
    s/[][]//g;  # remove [ and ]
    h;          # put into the hold-space
}

/=/{            # handle settings
    H;          # append the line to the hold-space with newline as delimiter
    g;          # get the hold-space
    s/\n/./;    # replace the newline with a dot
    p;          # output
    s/\..*//;   # remove everything after the dot
    h;          # put back into the hold-space
}
    
por 19.05.2018 / 09:41