나는 몇 가지 bash ini 구문 분석 스크립트를 보았고 다음을 보았습니다.이것하나는 여기에서 몇 번 사용되었으므로 그것이 나에게 효과가 있는지 알아보려고 노력하고 있습니다. ini 파일을 한 줄씩 여러 번 읽고 각 패스마다 최종적으로 평가되는 함수를 점진적으로 구성하는 것처럼 보입니다. 일부 특수 문자에는 잘 작동하지만 다른 문자에는 잘 작동하지 않습니다. 파일의 값에 작은따옴표 또는 보다 큼/작음 기호가 포함되어 있으면 스크립트는 구문 오류를 반환합니다. 다른 기호도 예상치 못한 결과를 낳습니다. 이러한 문자가 나타날 때 어떻게 처리할 수 있습니까?
ini를 파싱하는 함수입니다.
#!/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 be =
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
}
ini 파일
[Section1]
value1=abc`def # unexpected EOF while looking for matching ``'
value2=ghi>jkl # syntax error near unexpected token `>'
value3=mno$pqr # executes ok but outputs "mnoqr"
value4=stu;vwx # executes ok but outputs "stu"
답변1
당신이~할 수 있다뭔가를 하라는 bash
뜻은 아니야~해야 한다.
sh
(및 bash
기타) 스크립트는 프로그램을 시작하거나 텍스트 처리 명령을 중심으로 하는 상대적으로 간단한 래퍼에 가장 적합합니다. ini 파일을 구문 분석하고 이에 대한 작업을 수행하는 등 더 복잡한 작업의 경우 다른 언어가 더 적합합니다. perl
또는 에서 스크립트 작성을 고려해 보셨나요 python
? 둘 다 좋은 .ini 파일 파서를 가지고 있습니다. Config::INI
저는 ini 파일을 파싱해야 할 때 Perl의 모듈을 여러 번 사용했습니다 .
그러나 Bash에서 이를 고집한다면 개별 변수를 설정하는 대신 연관 배열을 사용해야 합니다.
다음과 같이 시작하십시오.
#! /bin/bash
inifile='user1074170.ini'
# declare $config to be an associative array
declare -A config
while IFS='=' read -r key val ; do
config["$key"]="$val"
done < <(sed -E -e '/^\[/d
s/#.*//
s/[[:blank:]]+$|^[[:blank:]]+//g' "$inifile" )
# now print out the config array
set | grep '^config='
스크립트 는 줄 sed
을 삭제하고 [Section1]
(실제로 여는 대괄호로 시작하는 모든 줄 [
- 여러 섹션이 있는 ini 파일에서 이를 다르게 처리해야 합니다 [1] ). 주석과 앞뒤 공백을 제거합니다. 루프 는 필드 구분 기호를 while
사용하여 각 줄을 읽고 =
$key 및 $val 변수에 내용을 할당한 다음 $config 배열에 추가합니다.
산출:
config=([value1]="abc\`def" [value3]="mno\$pqr" [value2]="ghi>jkl" [value4]="stu;vwx" )
나중에 스크립트에서 다음과 같이 배열 항목을 사용할 수 있습니다.
$ echo value1 is "${config[value1]}"
value1 is abc`def
$ [ "${config[value4]}" = 'stu;vwx' ] && echo true
true
[1] awk
또는 perl
"단락" 모드에서 파일을 읽는 편리하고 쉬운 방법이 있습니다. 하나 이상의 빈 줄로 다른 텍스트 블록과 구분된 텍스트 블록으로 정의되는 단락입니다.
예를 들어 로만 작업하려면 위의 루프 에 공급되는 스크립트 바로 앞에 아래 스크립트를 [Section1]
삽입하세요 .awk
sed
while
awk -v RS= -v ORS='\n\n' '/\[Section1\]/' "$inifile" | sed ...
( 물론 명령줄 "$inifile"
끝에서 제거 sed
하십시오. 파일에서만 추출하는 수고를 겪은 후에 파일을 다시 공급하고 싶지는 않을 것입니다 [Section1]
).
ini 파일에서 하나의 섹션만 추출하는 경우 설정이 ORS
꼭 필요한 것은 아니지만 두 개 이상의 섹션을 추출하는 경우 단락 구분을 유지하는 데 유용합니다.
답변2
나는 그것이 불완전한 대답이라는 것을 알고 있지만 MySQL.lns
in augeas는 그 대부분을 구문 분석할 수 있는 것 같습니다. 안에 augtool
:
augtool> set /augeas/load/testini/incl "/root/test.ini"
augtool> set /augeas/load/testini/lens "MySQL.lns"
augtool> load
augtool> ls /files/root/
.ssh/ test.ini/
augtool> ls /files/root/test.ini
target/ = Section1
augtool> ls /files/root/test.ini/target/
value1/ = abc`def
value2/ = ghi>jkl
value3/ = mno$pqr
value4/ = stu
유일하게 엉망인 것은 마지막 것이고 TBH는 오류가 아닌 것 같습니다. 파일 에서 .ini
세미콜론은 주석의 시작을 표시합니다. 또한 귀하의 데이터가 실제로 그렇게 보이는지 묻고 싶습니다.
그렇다면 사용되지 않은 문자 값으로 sed
설정하기 전에 일부 작업을 수행 ;
한 다음 사후 처리로 다시 변환할 수 있습니다. 그러나 궁극적으로 파일이 식별 가능한 구조를 가질 수 있으려면 몇 가지 표준이 필요합니다.
편집하다:
나는 PHP 렌즈로 그것을 테스트했고 값이 인용되는 한 모든 것을 얻었습니다.
[root@vlzoreman ~]# augtool
augtool> set /augeas/load/testini/lens "PHP.lns"
augtool> set /augeas/load/testini/incl "/root/test.ini"
augtool> load
augtool> ls /files/root/test.ini/Section1/
value1 = abc`def
value2 = ghi>jkl
value3 = mno$pqr
value4 = stu;vwx
그렇지 않으면 MySQL 렌즈만큼 멀리 떨어져 있습니다.
편집 #2:
이것을 작성하는 더 깔끔한 방법이 있다고 확신하지만 이는 예제 사용법입니다.
[root@vlp-foreman ~]# bash bash.sh
Values for: Section1:
:: value1 is abc`def
:: value2 is ghi>jkl
:: value3 is mno$pqr
:: value4 is stu;vwx
Values for: Section2:
:: value1 is abc`def
스크립트는 다음과 같습니다
#!/bin/bash
sections=$(augtool -A --transform "PHP.lns incl /root/test.ini" ls /files/root/test.ini | cut -f1 -d/)
for currentSection in $sections; do
echo "Values for: $currentSection:"
fields=$(augtool -A --transform "PHP.lns incl /root/test.ini" ls /files/root/test.ini/$currentSection | awk '{print $1}')
for currentField in $fields; do
currentValue=$(augtool -A --transform "PHP.lns incl /root/test.ini" print /files/root/test.ini/$currentSection/$currentField | cut -f2 -d=)
currentValue=$(echo $currentValue | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//' | sed -e 's/^"//' -e 's/"$//')
echo -e "\t:: $currentField is $currentValue"
done
done
답변3
보세요 crudini
:https://www.pixelbeat.org/programs/crudini/
sudo apt install crudini
Ubuntu에서는 ini 파일에서 값을 읽으려면 다음을 실행하여 설치할 수 있습니다 .
$ value1=$(crudini --get "crudini.ini" "Section1" "value1")
crudini는 여러 형식의 ini 파일을 지원하고 특수 문자를 처리합니다.
crudini.ini
[Section1]
value1=abc`def
value2=ghi>jkl
value3=mno$pqr
value4=stu;vwx
가치 읽기
$ for i in {1..4}; do crudini --get "crudini.ini" "Section1" "value$i"; done
abc`def
ghi>jkl
mno$pqr
stu;vwx
$