Bash 스크립트 중간에 다음과 같은 문자열 배열이 있다고 상상해 봅시다:
example1.log
example1.log.1
log2.log
xpto.log
xpto.log.1
xpto.log.2
다음 형식의 문자열을 포함하는 연관 배열(원하는 배열 구조의 표현)로 변환하는 방법이 있습니까?
{
"example1" : [ "example1.log", "example1.log.1" ],
"log2" : [ "log2.log" ],
"xpto" : [ "xpto.log", "xpto.log.1", "xpto.log.2" ]
}
노트:
- 초기 문자열은 항상
non-predictable-name
+.log
+ 와 유사한 형식을 갖습니다.x
(선택적 점 및 정수).
감사해요.
답변1
해결책은 다음과 같습니다 bash
(버전 >= 4).
declare -A logs
for logfile in *; do
logs[${logfile%%.*}]+="$logfile "
done
연관 배열을 사용하는 예로 다음과 같이 인쇄할 수 있습니다.
for log in "${!logs[@]}"; do
echo "$log:"
for file in ${logs[$log]}; do
echo "- $file"
done
done
(로그 파일 이름에 공백이 없다고 가정합니다)
답변2
bash
연관 배열은 단점에도 불구하고 의 배열에서 영감을 얻었 지만 ksh93
해당 값에 스칼라 이외의 다른 항목을 할당하는 것을 지원하지 않습니다.
값이 배열이 될 수 있는 연관 배열의 경우 다음이 필요합니다 ksh93
.
$ ksh -c 'typeset -A logs; for f in *.log*; do logs[${f%.log*}]+=($f); done; typeset -p logs'
typeset -A logs=([example1]=(example1.log example1.log.1) [log2]=(log2.log) [xpto]=(xpto.log xpto.log.1 xpto.log.2) )
이를 반복하려면 다음을 수행하십시오.
typeset -A logs
for f in *.log*; do logs[${f%.log*}]+=($f); done
for key in "${!logs[@]}"; do
printf '%s:\n' "$key"
for file in "${logs[$key][@]}"; do
printf ' File: "%s"\n' "$file"
done
done
zsh
연관 배열은 스칼라 값만 가질 수 있지만 이러한 값에는 NUL 문자가 포함될 수 있으므로 임의의 파일 이름 목록을 NUL 문자로 구분하여 저장할 수 있습니다. 를 사용하세요 bash
. 파일 이름은 모두 현재 디렉터리에 있으므로 로 구분할 수 있습니다 /
. 또는 파일 이름에 특정 문자가 없다고 가정할 수 있는 경우 이를 사용할 수 있습니다(예: @xhienne의 공백 문자 접근 방식). 또한 bash
연관 배열에는 키가 null일 수 없다는 제한 사항이 있습니다.
답변3
cat - <<\eof |
example1.log
example1.log.1
log2.log
xpto.log
xpto.log.1
xpto.log.2
eof
perl -lne '
/(.*)\.log(?=\.\d+$|$)/ and
push(@{$h{$1}}, qq/"$_"/), $h[-1+keys %h]=$1;
END{
print for
q/{/,
join(",\n",
map {
join($",
qq/\t"$_"/,
q/:/,
q/[/,
join(", ", @{$h{$_}}),
q/]/,
)
} @h
),
q/}/
}
'
산출
{
"example1" : [ "example1.log", "example1.log.1" ],
"log2" : [ "log2.log" ],
"xpto" : [ "xpto.log", "xpto.log.1", "xpto.log.2" ]
}