![속성 파일을 연관 배열로 읽는 방법은 무엇입니까?](https://linux55.com/image/90677/%EC%86%8D%EC%84%B1%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EC%97%B0%EA%B4%80%20%EB%B0%B0%EC%97%B4%EB%A1%9C%20%EC%9D%BD%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
속성을 읽고 싶습니다.속성 파일연관 배열로.어떻게 해야 합니까?
구문 분석 대상에 대한 세부정보: 해시 및 등호. 다른 모든 것은 보너스입니다.
속성 파일 내용의 예:
# comment
a=value-a
b=http://prefix.suffix:8080/?key=value
c=password_with\\backslash-and=equals
이 파일에서 bash 연관 배열을 구성하고 싶습니다.
declare -A props='(
[a]="value-a"
[b]="http://prefix.suffix:8080/?key=value"
[c]="password_with\\backslash-and=equals" )'
declare -p
(이 연관 배열 note의 예상 출력에는 ${props[c]}
백슬래시가 하나만 포함됩니다. "\\"
즉 '\'
).
답변1
perl
' 와 같은 실제 파서를 사용하십시오 .Config::Properties
기준 치수. 에서 전체 스크립트를 완료하겠지만 perl
을 사용해야 하는 경우 bash
다음을 수행할 수 있습니다.
typeset -A props
while IFS= read -rd '' key && IFS= read -rd '' value; do
props[$key]=$value
done < <(
perl -MConfig::Properties -l0 -e '
$p = Config::Properties->new();
$p->load(STDIN);
print for $p->properties' < file.properties
)
(에도 적용됩니다 zsh
).
완전한 파서를 구현하려면 bash
많은 작업이 필요하며 바퀴를 다시 개발해야 합니다. 내장 함수에는 다음 속성 파일과 매우 유사한 입력 형식이 필요하므로 while read
간단한 루프를 사용하여 좋은 하위 집합을 얻을 수 있습니다 .read
typeset -A props
while IFS=$':= \t' read key value; do
[[ $key = [#!]* ]] || [[ $key = "" ]] || props[$key]=$value
done < file.properties
( 연관 배열을 지원하는 두 개의 다른 Bourne 유사 쉘인 ksh93
및 와 함께 사용할 수도 있습니다 ).zsh
이는 다음을 처리합니다.
prop = value
prop: value
prop value
- 주석은 줄의 시작 부분에 있습니다(
!
선택적#
으로 선행 공백이 있습니다). - 백슬래시 이스케이프(구분 기호 또는 가 포함된 키의 예에서와 같이
foo\:\:bar=value
)foo=\ bar
password_with\\backslash-and=equals
- 백슬래시를 사용한 줄 연속
그런데 확인해 보면사양
\n
,\r
,\uXXXX
... 시퀀스를 처리하지 않습니다.LF는 유일하게 인식되는 줄 구분 기호입니다(CR이나 CRLF가 아님).
$IFS
FF는 공백으로 인식되지 않습니다( 쉘과 버전에 따라\f
반드시 IFS 공백 문자 1로 인식되는 것은 아니기 때문에 여기에 추가할 수는 없습니다 ).와 같은 입력의 경우 대신
foo: bar =
저장하세요bar
( 그러나 그것도 작동합니다). 속성 값에 (이스케이프되지 않은) 구분 기호( 선택적으로 SPC/TAB 문자로 묶이거나 선택적으로 SPC/TAB 문자로 묶이거나 하나 이상의 SPC/TAB 문자 시퀀스)가 포함되어 있고 끝에 있는 경우에만 문제가 발생합니다. .${props[foo]}
bar =
foo: bar:baz:
:
=
\!
또는 로 시작하는 주석 줄로 처리됩니다\#
. 이름이 또는 로 시작하는 속성에만!
문제가 있습니다#
.존재하다
prop=1\ 2\ 3
우리가 얻는 것은 1 2 3
연속 123
된 줄의 선행 공백이 무시되지 않는다는 것입니다.
²IFS 공백 문자[:space:]
, 각 POSIX는 로케일(일반적으로 포함되지만 \f
필수는 아님)로 분류된 문자이며 정확히 $IFS
ksh88(POSIX 사양의 기반)이며 대부분의 셸에서는 여전히 SPC, TAB 및 NL로 제한됩니다. 이와 관련하여 제가 찾은 유일한 POSIX 호환 셸은 입니다 yash
. ksh93
( bash
5.0 기준) 다른 공백(예: CR, FF, VT...)도 포함하지만 단일 바이트 공백으로 제한됩니다(예: Solaris)(일부 영역에는 단일 바이트의 잘림 방지 공백이 포함됨)
답변2
Bash4+에서 수행하는 방법은 다음과 같습니다.
#!/usr/bin/env bash
declare -A properties
# Read with:
# IFS (Field Separator) =
# -d (Record separator) newline
# first field before separator as k (key)
# second field after separator and reminder of record as v (value)
while IFS='=' read -d $'\n' -r k v; do
# Skip lines starting with sharp
# or lines containing only space or empty lines
[[ "$k" =~ ^([[:space:]]*|[[:space:]]*#.*)$ ]] && continue
# Store key value into assoc array
properties[$k]="$v"
# stdin the properties file
done < file.properties
# display the array for testing
typeset -p properties
file.properties
:
# comment
a=value-a
b=http://prefix.suffix:8080/?key=value
c=password_with\\backslash-and=equals
d e=the d e value
# comment
제공된 데이터 샘플에 있는 이 스크립트의 출력은 다음과 같습니다.
declare -A properties=(["d e"]="the d e value" [c]="password_with\\\\backslash-and=equals" [b]="http://prefix.suffix:8080/?key=value" [a]="value-a" )
답변3
이 데이터 형식의 가장 일반적인 하위 집합의 경우 다음을 사용하여 짧은 함수를 사용할 수 있습니다.bash 변수 확장정규식과 일치합니다.
^key = value$
참고: 이 줄은 형식 이 있거나 주석 ^#.*$
에 사용되어야 합니다 . ^!.*$
코드를 조정하거나 데이터를 전처리합니다.
$ cat /tmp/propdata
k1 = v1
# A comment
k2 = v2and some s=t=u=f=f
! Another comment
k3 = v3
$ unset DATA
$ declare -A DATA
$ props(){ while read line || [[ -n $line ]]; do
[[ "$line" =~ ^#|^! ]] && continue;
if [[ "${line% =*}" ]]; then DATA[${line% =*}]="${line#*= }" ; fi ;
done < $1 ; }
$ props /tmp/propdata
$ echo "${DATA[k3]}"
v3
$ echo "${DATA[k2]}"
v2and some s=t=u=f=f
편집: 키와 값에 대해 "=" 주위의 공백을 잘라내도록 업데이트되었습니다.
Edit2: 이제 댓글도 필터링하세요.
답변4
declare -A properties
function readPopertyFile
{
while read line || [[ -n $line ]]; do
key=`echo $line | cut -s -d'=' -f1`
if [ -n "$key" ]; then
value=`echo $line | cut -d'=' -f2-`
properties["$key"]="$value"
fi
done < $1
}
용법:
readPopertyFile "file.properties"
속성은 라는 연관 배열 변수로 읽혀집니다 properties
.
* 배쉬에서 작동합니다. 다른 껍질에 대해서는 잘 모르겠습니다.
* 여러 줄 속성은 처리되지 않습니다.