Newsgroup: it.comp.os.linux.sys
Titolo: Bash e parsing file di configurazione

ciao lista,
avrei bisogno di creare uno script in grado di leggere un proprio file
di configurazione per compiere determinate azioni...
Mi spiego meglio:
Vorrei avere un file 
ad.es
. /etc/probe/probe.conf
con una struttura tipo:
[NOME-A]
[PARAMETRO1] = [PIPPO]
[PARAMETRO2] = [VALORE]
[PARAMETRO3] = [VALORE]
[PARAMETRO4] = [VALORE]
[PARAMETRO5] = [VALORE]
[NOME-B]
[PARAMETRO1] = [VALORE]
[PARAMETRO2] = [VALORE]
[NOME-C]
[PARAMETRO4] = [VALORE]
[PARAMETRO5] = [VALORE]
Oppure...e forse più bella da vedere...
NOME-A {
[PARAMETRO1] = [PIPPO]
[PARAMETRO2] = [VALORE]
[PARAMETRO3] = [VALORE]
[PARAMETRO4] = [VALORE]
[PARAMETRO5] = [VALORE]
}
NOME-B {
[PARAMETRO1] = [VALORE]
[PARAMETRO2] = [VALORE]
}
...e uno script in grado di fare il parsing di questo file di
configurazione per popolarmi determinate variabili...
ed.es
.
CONF_FILE = /etc/probe/probe.conf
$TUTTI_NOMI = "NOME-A NOME-B"
e discendendo all' interno di NOME-A ottenere per esempio $parametro1
= "PIPPO"
Qualcuno mi sa dare due dritte su come costruire uno script di questo
tipo?
Esempi e guide son ben ' accette!
Grazie!




ops scusate il doppio post!

> [PARAMETRO1] = [PIPPO]
questo si chiama file di tipo "ini"
non esiste un parser ufficiale in bash, in pyhton sarebbe molto piu'
semplice.
comunque puoi partire da qua:
http://ajdiaz.wordpress.com/2008/02/09/bash-ini-parser/



Barbatrucco (che potrebbe anche non fare al caso tuo, ma tant'e'):
Crei il tuo file cosi' (ad esempio):
# probe.conf
# SEZIONE1
PAR1=VAL1
PAR2="VAL 2"
PAR3=FOOBAR
# SEZIONE2
PAR4=AAA
PAR5="BBB CCC DDD"
PAR6="EEE FFF GGG"
# etc.etc.
e poi nel tuo script fai
. /path/to/probe.conf
e automagicamente hai tutti i valori assegnati ai relativi parametri, quindi
nell'esempio puoi usare la variabile $PAR3 nel tuo script e avra'
valore "FOOBAR" (lo stesso per le altre).
Questo, come detto, e' un barbatrucco, non e' robusto, ma e' molto comodo se
non hai particolari esigenze e sarai tu a gestire il file di
configurazione, creandolo in modo da non avere errori di sintassi o altri
problemi. Ovviamente non e' un sistema praticabile se devi dare la cosa in
mano a degli utenti (o utonti). Inoltre, non e' praticabile se hai
assolutamente bisogno della sintassi "SEZIONE1 PAR1" per accedere a un
certo valore, in quanto non e' "strutturato" ma e' un semplice file flat
che viene interpretato dalla shell.
Per cose piu' complesse, hai solo l'imbarazzo della scelta tra formati
standard come .ini, .xml etc. anche se in quel caso forse e' meglio usare
un linguaggio che abbia il supporto (nativo o tramite moduli aggiuntivi)
per tali formati, come ad esempio Python o Perl.



il problema è che così le sezioni perdono di significato.
In questo modo quindi non puoi avere una variabile con lo stesso nome
sotto due diverse sezioni, mentre lui ha specificato un formato
fatto proprio così.
Pibadisco che con file del genere python (con i suoi dizionari) , php
(con gli array) vanno a nozze. Sicuro che andrebbero bene anche perl ,
ruby e compagnia bella, ma li conosco poco.

 - Mostra testo citato -
Esatto, purtroppo così non ha molto senso...più che altro dovrà essere
gestito da persone non troppo esperte e un semplice buco nella
numerazione farebbe crollare tutto il senso dello script..
come potrei risolvere?

 come potrei risolvere?
te l'abbiamo già detto tutti, usa un linguaggio adatto a fare questo tipo
di cose.
ad esempio , guarda quante belle ricettine precotte:
http://www.google.it/search?hl=it&rlz=1G1GGLQ_ITIT276&q=python+ini+parser&btnG=Cerca&meta=

 
http://www.google.it/search?hl=it&rlz=1G1GGLQ_ITIT276&q=python+ini+pa.
..
non mi va di dover apprendere un linguaggio dedicato allo scopo quando
per il 99 % mi basta bash...
a questo punto rivedo l' idea del file di configurazione...
farei a questo punto una file di configurazione del tipo
NOME <tab> PAR1 <tab> PAR2 <tab> PAR3 <tab> PAR4
sarebbe + facile da leggere?
riuscite a farmi un esempio dal quale prendere spunto?



Interessante, io avevo appena finito di metter su un simil-accrocchio :-) [1]
http://pastebin.com/f6d12a3e
Ovviamente, non avendo pensato fosse un "ini", ho supportato i commenti "#"
invece che ";" :-)
Comunque, il mio script ha un approccio un attimo diverso. Non fa eval() di
niente, andrebbe messo dentro una funzione e richiamato come
funzione sezione variabile
da dentro lo script Bash dell'OP.
Mi sa che darò un'occhiata più approfondita al link che hai postato :-)
Kindly,
David
[1] ora capisco perché un mio amico mi definì "scimmia da codice" una volta. :/
-- 
 . ''`.  Debian maintainer | 
http://wiki.debian.org/DavidPaleino
 : :'  : Linuxer #334216 --|-- 
http://www.hanskalabs.net/
 `. `'`  GPG: 1392B174 ----|---- 
http://snipr.com/qa_page
   `-   2BAB C625 4E66 E7B8 450A C3E1 E6AA 9017 1392 B174

 riuscite a farmi un esempio dal quale prendere spunto?
ti consiglio di prendere spunto dal link che ti ho postato nell'altra
riposta:
http://ajdiaz.wordpress.com/2008/02/09/bash-ini-parser/
io ogni tanto lo uso (con le sue limitazioni)

 volta. :/
rotfl

 
http://pastebin.com/f6d12a3e
provato, molto carino e soprattutto mi hai fatto scoprire uno strumento 
che non conoscevo (=~ e $BASH_REMATCH)!
un appunto, le verifiche sulle regexp non funzionno sulla mia shell, a
meno di mettere tutto tra apici, quindi:
if [[ "$line" =~ "^\[(.*)\]" ]]; then
if [[ "$line" =~ "^\s*([^\s]+)\s*=\s*([^\s].*)\s*#?" ]]; then

 if [[ "$line" =~ "^\s*([^\s]+)\s*=\s*([^\s].*)\s*#?" ]]; then
Che shell usi?
Perché nella mia bash =~ considera regex tutto ciò che viene dopo lo spazio --
quindi se racchiudo tutto tra "" non va una cippa:
~ $ [[ "ciao" =~ ^c ]] && echo true
true
~ $ [[ "ciao" =~ "^c" ]] && echo true
~ $
Cosa usi, dash? Magari è un bug da segnalare :)
Ciao,
David


 invece che ";" :-)
mi sono messo a giochicchiare col tuo script, una aggiunta che potresti
fare è questa:
if [ "${BASH_REMATCH[1]}" == "$SECTION" ]; then
	# controllo correttezza file di configurazione
	if [ "$_section" != "" ];then
		echo "Errore: due sezioni con lo stesso nome"
		exit # qua mettici un po' quello che ti pare, ma credo che exit sia la
		     #cosa migliore
	fi
	is_inside=1
	continue
else
poi, invece del giochino 
OIFS="$IFS"
IFS=$'\n'
...
...
IFS="$OFS"
basta fare:
IFS=$'\n'
...
...
unset IFS

 Cosa usi, dash? Magari è un bug da segnalare :)
$ bash --version
GNU bash, version 3.1.17(2)-release (i486-slackware-linux-gnu)

 GNU bash, version 3.1.17(2)-release (i486-slackware-linux-gnu)
Il comportamento è cambiato tra bash 3.1 e 3.2:
$ bash --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
http://tiswww.case.edu/php/chet/bash/CHANGES
---
This document details the changes between this version, bash-3.2-alpha,
and the previous version, bash-3.1-release.
[..]
3.  New Features in Bash
[..]
f.  Quoting the string argument to the [[ command's  =~ operator now forces
    string matching, as with the other pattern-matching operators.
---
Per essere backwards-compatible, la regex dovrebbe esser messa in una variabile:
---
re="^\[(.*)\]"
[[ "[Foo]" =~ $re ]] && echo true;
---
(credo funzioni, confermamelo please :))


 (credo funzioni, confermamelo please :))
confermo


Vi sto perdendo...
parlate facile io sono niubbio!
le regex le ho usate su perl con bash poche volte e sinceramente
dovrei ristudiarele tutte...
potrei popolare degli array partendo da valori separati da
tabulazioni?
dato un file tipo...
aa1   bb2  cc3  dd4  ee5
aa1   cc3
o è meglio piuttosto mettere dei valori nulli (chessò un' "-") per i
valori da non considerare?
tipo:
aa1   bb2  cc3  dd4  ee5
aa1   -      cc3  -       -
mi fate un esempio per tirare fuori i valori? cosa devo usare? awk?

 mi fate un esempio per tirare fuori i valori? cosa devo usare? awk?
oddio, sono io che non ti seguo, che c'entra sta roba con la tua domanda
iniziale?
stavamo parlando di un parser per file ini 
il problema di questi script è che ogni volta che cerchi una variabile,
devi rilanciare il parser, pero' funzionano 


Sto cercando una soluzione per poter avere delle variabili che
caricano il proprio valore da un  file esterno...
Tralasciano l' ipotesi del file ini , poichè mi pare essere abbastanza
complicata io ho la "semplice" esigenza di caricare valori da un file
esterno...

 avrei bisogno di creare uno script in grado di leggere un proprio file
]zac[
Se vuoi cerca il programma gesconf su google (lo trovi nel sito savannah) è
stato pensato apposta per l'uso negli script.
Poi se vuoi un esempio reale di utilizzo cerca scriptbackup (nello stesso
posto).

 ... se vuoi gesconf gestisce i file senza gruppi, con un livello di gruppi,
con gruppi annidati ... e tanto per informazione, anche il file di
configurazione di X (xorg.conf).