Właśnie skończyłem pisać własny parser. Próbowałem użyć różnych parserów znalezionych tutaj, żaden nie działa zarówno z ksh93 (AIX), jak i bash (Linux).
To stary styl programowania - parsowanie linia po linii. Dość szybko, ponieważ używał kilku poleceń zewnętrznych. Nieco wolniej ze względu na wszystkie eval wymagane dla dynamicznej nazwy tablicy.
Ini obsługuje 3 specjalne składnie:
- includeefile = ini file -> Załaduj dodatkowy plik ini. Przydatne do dzielenia ini na wiele plików lub ponownego wykorzystania jakiejś części konfiguracji
- includedir = directory -> To samo, co includeefile, ale zawiera pełny katalog
- obejmuje sekcję = sekcja -> Skopiuj istniejącą sekcję do bieżącej sekcji.
Użyłem całej tej składni, aby uzyskać dość złożony, wielokrotnego użytku plik ini. Przydatne do instalowania produktów podczas instalowania nowego systemu operacyjnego - robimy to często.
Dostęp do wartości można uzyskać za pomocą $ {ini [$ section. $ Item]}. Tablica MUSI zostać zdefiniowana przed wywołaniem tego.
Baw się dobrze. Mam nadzieję, że będzie to przydatne dla kogoś innego!
function Show_Debug {
[[ $DEBUG = YES ]] && echo "DEBUG $@"
}
function Fatal {
echo "$@. Script aborted"
exit 2
}
function Load_Ini {
Show_Debug "$0($@)"
typeset ini_file="$1"
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=""
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
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%%=*}
value=${line#*=}
if [[ $variable = includefile ]]; then
Load_Ini "$include_directory/$value" "$ini_array_name"
continue
elif [[ $variable = includedir ]]; then
if [[ $value != /* ]]; then
value="$include_directory/$value"
fi
for file in $(ls $value/*.ini 2>/dev/null); do
if [[ $file != *.ini ]]; then continue; fi
Load_Ini "$file" "$ini_array_name"
done
continue
elif [[ $variable = includesection ]]; then
eval "all_index=\"\${!$ini_array_name[@]}\""
for index in $all_index; do
if [[ $index = $value.* ]]; then
subsection=${index#*.}
eval "value_array=\"\${$ini_array_name[$index]}\""
eval "$ini_array_name[$section.$subsection]=\"\$value_array\""
Show_Debug "$ini_array_name[$section.$subsection]=\"$value_array\""
fi
done
fi
eval "current_value=\"\${$ini_array_name[$section.$variable]}\""
new_value="$current_value${current_value:+$LF}$value"
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"
}