속성 파일을 연관 배열로 읽는 방법은 무엇입니까?

속성 파일을 연관 배열로 읽는 방법은 무엇입니까?

속성을 읽고 싶습니다.속성 파일연관 배열로.어떻게 해야 합니까?

구문 분석 대상에 대한 세부정보: 해시 및 등호. 다른 모든 것은 보너스입니다.

속성 파일 내용의 예:

# 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=\ barpassword_with\\backslash-and=equals
  • 백슬래시를 사용한 줄 연속

그런데 확인해 보면사양

  • \n, \r, \uXXXX... 시퀀스를 처리하지 않습니다.

  • LF는 유일하게 인식되는 줄 구분 기호입니다(CR이나 CRLF가 아님).

  • $IFSFF는 공백으로 인식되지 않습니다( 쉘과 버전에 따라 \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필수는 아님)로 분류된 문자이며 정확히 $IFSksh88(POSIX 사양의 기반)이며 대부분의 셸에서는 여전히 SPC, TAB 및 NL로 제한됩니다. 이와 관련하여 제가 찾은 유일한 POSIX 호환 셸은 입니다 yash. ksh93( bash5.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.

* 배쉬에서 작동합니다. 다른 껍질에 대해서는 잘 모르겠습니다.

* 여러 줄 속성은 처리되지 않습니다.

관련 정보