Для редактирования файлов "ini" из программы bash/dash создал такой "скрипт". Для работы требует наличия sed. Содержит следующие функции:
INI_TestFile filename commentsymbol - проверка на корректность конфигурационного файла;
INI_UnCommentKey FileName Section Key Comment CommentSymbol - удаляет символ комментария перед определением ключа;
INI_UnCommentKeys FileName Section CommentSymbol comment Key1 Key2....... - удаление символа комментария перед несколькиими ключами;
INI_ReadKey FileName Section Key CommentSymbol - читать значение ключа;
INI_TestExistKey FileName Section Key CommentSymbol - проверка наличия ключа в конфигурационном файле;
INI_TestExistSection FileName Section CommentSymbol - проверка наличия секции в конфигурационном файле;
INI_WriteKey FileName Section Key Value comment CommentSymbol - изменение значения ключа
Тескт под катом.
INI_TestFile filename commentsymbol - проверка на корректность конфигурационного файла;
INI_UnCommentKey FileName Section Key Comment CommentSymbol - удаляет символ комментария перед определением ключа;
INI_UnCommentKeys FileName Section CommentSymbol comment Key1 Key2....... - удаление символа комментария перед несколькиими ключами;
INI_ReadKey FileName Section Key CommentSymbol - читать значение ключа;
INI_TestExistKey FileName Section Key CommentSymbol - проверка наличия ключа в конфигурационном файле;
INI_TestExistSection FileName Section CommentSymbol - проверка наличия секции в конфигурационном файле;
INI_WriteKey FileName Section Key Value comment CommentSymbol - изменение значения ключа
Тескт под катом.
value=""
IFS=""
quote='"'
apostrophe="'"
INI_DivideOnZero ()
{
local zero=0
return $(( zero/zero ))
}
#INI_Terminate message
INI_Terminate ()
{
echo $1
INI_DivideOnZero
}
#VarDoubleSlash text
VarDoubleSlash ()
{
if [ $# -ne 1 ] ; then INI_Terminate "bad number of parameter VarDoubleSlash" ; fi
value=$(printf %s "$1" | sed -E 's/([\\/])/\\\1/g')
return $?
}
VarDoubleBackSlash
VarDoubleBackSlash ()
{
if [ $# -ne 1 ] ; then INI_Terminate "bad number of parameter VarDoubleBackSlash" ; fi
value=$(printf %s "$1" | sed -E 's/\\/\\\\/g')
return $?
}
VarDoubleDiv ()
{
if [ $# -ne 1 ] ; then INI_Terminate "bad number of parameter VarDoubleDiv" ; fi
value=$(printf %s "$1" | sed -E 's/\//\\\//g')
return $?
}
INI_Shielding()
{
if [ $# -ne 1 ] ; then INI_Terminate "bad number of parameter INI_Shielding" ; fi
printf %s $1 | sed -E 's/(\[|\]|[.*|+?$^{}()&\\\/])/\\\1/g'
if [ $? -ne 0 ] ; then INI_Terminate "INI_Shielding: bad sed" ; fi
}
#INI_TestFile filename commentsymbol
INI_TestFile ()
{
if [ $# -lt 1 ] ; then INI_Terminate "bad number of parameter INI_TestFile" ; fi
if [ $# -gt 2 ] ; then INI_Terminate "bad number of parameter INI_TestFile" ; fi
if [ ! -f $1 ] ; then return 1 ; fi # нет конфигурационного файла
local CS="#"
if [ ${#2} -eq 1 ] ; then CS=$2 ; fi
if ! sed -n "1 q" $1 ; then return 2 ; fi # обработка sed невозможна
#проверка на строки неправильного формата
if [ "BAD" = "$(sed -En "/^[[:blank:]]*($CS.*)*$/b good\
;/^[[:blank:]]*\[[[:blank:]]*[^$CS[:blank:]]+[^$CS]*\][[:blank:]]*($CS.*)*$/b good\
;/^([[:blank:]]*[^$CS[:blank:]]+[[:blank:]]*)*=.*$/b good\
;s/^.*$/BAD/ ; p ; q ; :good" $1)" ] ; then return 3 ; fi
if [ "BAD" = "$(sed -En "1,/^[[:blank:]]*\[[[:blank:]]*[^$CS[:blank:]]+[^$CS]*\][[:blank:]]*($CS.*)*$/{\
/^([[:blank:]]*[^$CS[:blank:]]+[[:blank:]]*)*=.*$/{s/^.*$/BAD/;p;q}}" $1)" ] ; then
return 4 # есть ключи перед оапределением секции
fi
return 0
}
#INI_UnCommentKey FileName Section Key Comment CommentSymbol
INI_UnCommentKey ()
{
local section=$(INI_Shielding "$2")
local key=$(INI_Shielding "$3")
local CS="#"
local C=""
if [ $# -lt 3 ] ; then INI_Terminate "bad number of parameter INI_UnCommentKey" ; fi
if [ $# -gt 5 ] ; then INI_Terminate "bad number of parameter INI_UnCommentKey" ; fi
if [ ${#5} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol INI_UnCommentKey" ; fi
if [ ${#5} -eq 1 ] ; then CS=$5 ; fi
if [ ${#4} -gt 0 ] ; then
if ! C=$(printf %s "$4" | sed -E "s/(\\\\n)/\1$CS/g;s/^(.)/$CS\1/;s/(.)$/\1\\\\n/") ; then INI_Terminate "INI_UnCommentKey error exec sed" ; fi
if ! C=$(printf %s $C | sed -E 's/(\[|\]|[.*|+?$^{}()&])/\\\1/g') ; then INI_Terminate "INI_UnCommentKey error exec sed" ; fi
fi
if INI_TestExistKey $1 $2 $3 $5 ; then
printf %s "!!!Warning!!! key \"$3\" in section \"$2\" in file \"$1\" already uncomment" ; return 0
fi
if [ "YES" != "$(sed -En "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/, \
/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/ \
{/^([[:blank:]]*)$CS+([[:blank:]]*$key[[:blank:]]*\
=[[:blank:]]*(([^$CS[:blank:]]+([[:blank:]]*[^$CS[:blank:]]+)*)*)\
[[:blank:]]*($CS.*)*)$/ {s/^.*$/YES/ ;p ;q}}" $1)" ] ; then
printf %s "!!!Warning!!! comment key \"$3\" in section \"$2\" do not consist in file \"$1\"" ; return 0
fi
if [ "YES" != "$(sed -En "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/,\
/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/ \
{/^([[:blank:]]*)$CS+([[:blank:]]*$key[[:blank:]]*=[[:blank:]]*\
([^$CS[:blank:]]+([[:blank:]]*[^$CS[:blank:]]+)*)[[:blank:]]*($CS.*)*)$/ {s/^.*$/YES/ ;p ;q}}" $1)" ] ; then
printf %s "!!!Warning!!! comment key \"$3\" in section \"$2\" in file \"$1\" do not consist any value"
fi
sed -Ei "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/,\
/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/{\
s/^([[:blank:]]*)$CS+([[:blank:]]*$key[[:blank:]]*=[[:blank:]]*\
(([^$CS[:blank:]]+([[:blank:]]*[^$CS[:blank:]]+)*)*)[[:blank:]]*($CS.*)*)$/$C\1\2/}" $1
return $?
}
#INI_UnCommentKeys FileName Section CommentSymbol comment Key1 Key2.......
INI_UnCommentKeys ()
{
local FileName=$1
local section=$2
if [ ${#3} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol INI_UnCommentKeys" ; fi
local CS=$3
local comment=$4
while [ -n "$5" ]
do
INI_UnCommentKey $FileName $section $5 $comment $CS
shift
done
}
#INI_ReadKey FileName Section Key CommentSymbol
INI_ReadKey ()
{
local section=$(INI_Shielding "$2")
local key=$(INI_Shielding "$3")
local CS="#"
if [ $# -lt 3 ] ; then INI_Terminate "bad number of parameter INI_ReadKey" ; fi
if [ $# -gt 4 ] ; then INI_Terminate "bad number of parameter INI_ReadKey" ; fi
if [ ${#4} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol" ; fi
if [ ${#4} -eq 1 ] ; then CS=$4 ; fi
if ! INI_TestExistKey $1 $2 $3 $4 ; then return 255 ; fi
value=$(sed -nE "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.+)*$/,\
/^[[:blank:]]*\[.*\][[:blank:]]*($CS.+)*$/{\
s/^[[:blank:]]*$key[[:blank:]]*=[[:blank:]]*([^$CS[:blank:]]+([[:blank:]]*[^$CS[:blank:]]+)*)[[:blank:]]*($CS.+)*$/\1/p}" $1)
return $?
}
# INI_TestExistKey FileName Section Key CommentSymbol
INI_TestExistKey ()
{
local section=$(INI_Shielding "$2")
local key=$(INI_Shielding "$3")
local CS="#"
local begin=""
local end=""
if [ $# -lt 3 ] ; then INI_Terminate "bad number of parameter INI_TestExistKey" ; fi
if [ $# -gt 4 ] ; then INI_Terminate "bad number of parameter INI_TestExistKey" ; fi
if [ ${#4} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol" ; fi
if [ ${#4} -eq 1 ] ; then CS=$4 ; fi
if ! INI_TestExistSection $1 $2 $4 ; then return 255 ; fi
if [ "YES" = "$(sed -nr "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/,\
/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/{\
/^[[:blank:]]*$key[[:blank:]]*=.*$/ {s/^.*$/YES/ ;p ;q}}" $1)" ] ; then return 0 ; fi ; return 255
}
# INI_TestExistSection FileName Section CommentSymbol
INI_TestExistSection ()
{
local section=$(INI_Shielding "$2")
local CS="#"
if [ $# -lt 2 ] ; then INI_Terminate "bad number of parameter INI_TestExistSection" ; fi
if [ $# -gt 3 ] ; then INI_Terminate "bad number of parameter INI_TestExistSection" ; fi
if [ ${#3} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol" ; fi
if [ ${#3} -eq 1 ] ; then CS=$3 ; fi
if [ "YES" = "$(sed -nE "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/ {s/^.*$/YES/ ;p ;q}" $1)" ]
then return 0 ; fi
return 255
}
# INI_WriteKey FileName Section Key Value comment CommentSymbol
INI_WriteKey ()
{
local CS="#"
local C=""
local section=$(INI_Shielding "$2")
local key=$(INI_Shielding "$3")
local value=$(INI_Shielding "$4")
if [ $# -lt 4 ] ; then INI_Terminate "bad number of parameter INI_WriteKey" ; fi
if [ $# -gt 6 ] ; then INI_Terminate "bad number of parameter INI_WriteKey" ; fi
if [ $# -eq 6 ] ; then
if [ ${#6} -gt 1 ] ; then INI_Terminate "bad len of CommentSymbol INI_WriteKey" ; fi
CS=$6
fi
if [ ${#5} -gt 0 ] ; then
if ! C=$(printf %s "$5" | sed -E "s/(\\\\n)/\1$CS/g;s/^(.)/$CS\1/;s/(.)$/\1\\\\n/") ; then INI_Terminate "INI_WriteKey error exec sed" ; fi
if ! C=$(printf %s $C | sed -E 's/(\[|\]|[.*|+?$^{}()&])/\\\1/g') ; then INI_Terminate "INI_WriteKey error exec sed" ; fi
fi
if [ ! -f $1 ] ; then # если нет конфигурационного файла
echo "\n" | sed -E "1{s/^.*$/\[$section\]\n$C\n$key=$value/}">$1
if [ $? -ne 0 ] ; then INI_Terminate "INI_WriteKey error exec sed or write file" ; fi
return 0
fi
if ! INI_TestExistSection $1 $2 $6 ; then
if [ "YES" != "$(sed -nr "/^[[:blank:]]*$CS+[[:blank:]]*\[$section\]\
[[:blank:]]*($CS.*)*$/ {s/^.*$/YES/ ;p ;q}" $1)" ] ; then # если нет закомментированной секции, то дописать в конец файла новую секцию
echo "\n" | sed -E "1{s/^.*$/\n\[$section\]\n$C$key=$value/}">>$1
if [ $? -ne 0 ] ; then INI_Terminate "INI_WriteKey error exec sed or write file" ; fi
return 0
fi
#удаление комментария с секции
if ! sed -ri "s/^([[:blank:]]*)$CS+([[:blank:]]*\[$section\][[:blank:]]*($CS.*)*)$/\1\2/" $1 ; then
INI_Terminate "INI_WriteKey error exec sed or write file"
fi
fi
if ! INI_TestExistKey $1 $2 $3 $6 ; then # если нет ключа, то проверить на задокументированный ключ
if [ "YES" = "$(sed -nr "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/ \
,/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/ \
{/^[[:blank:]]*$CS+[[:blank:]]*$key[[:blank:]]*=.*$/ {s/^.*$/YES/ ;p ;q}}" $1)" ] ; then
# закомментированный ключ есть
if ! INI_UnCommentKey $1 $2 $3 "" $CS; then # убирание комментария не удалось
INI_Terminate "INI_WriteKey error INI_UnCommentKey"
fi
else
#ключа нет, добавление нового
if ! sed -ri "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/ a $C$key=$value" $1
then
INI_Terminate "INI_WriteKey error sed"
fi
fi
fi
# редактирование ключа
sed -ri "/^[[:blank:]]*\[$section\][[:blank:]]*($CS.*)*$/ \
,/^[[:blank:]]*\[.*\][[:blank:]]*($CS.*)*$/ \
{s/^([[:blank:]]*$key[[:blank:]]*=[[:blank:]]*)(([^$CS[:blank:]]+([[:blank:]]*[^$CS[:blank:]]+)*)*)([[:blank:]]*($CS.*)*)$/$C\1$value\5/}" $1
if [ $? -ne 0 ] ; then INI_Terminate "INI_WriteKey error" ; fi
}