모든 요소를 반복하지 않고 전체 배열([key]=value)을 인쇄하는 방법이 있습니까?
몇 가지 요소가 포함된 배열을 생성한다고 가정해 보겠습니다.
declare -A array
array=([a1]=1 [a2]=2 ... [b1]=bbb ... [f500]=abcdef)
전체 배열을 다시 인쇄할 수 있습니다.
for i in "${!array[@]}"
do
echo "${i}=${array[$i]}"
done
${!array[@]}
그러나 Bash는 모든 배열 요소(키 와 값) 를 한 번에 가져오는 방법을 이미 알고 있는 것 같습니다 ${array[@]}
.
반복하지 않고 bash에서 이 정보를 인쇄하도록 하는 방법이 있습니까?
편집:
typeset -p array
이렇게 하세요!
하지만 한 번에 접두사와 접미사를 모두 제거할 수는 없습니다.
a="$(typeset -p array)"
b="${a##*(}"
c="${b%% )*}"
출력의 key=value 부분만 가져오거나 인쇄하는 더 깔끔한 방법이 있습니까?
답변1
나는 당신이 거기에서 두 가지 다른 것을 요구하고 있다고 생각합니다.
반복하지 않고 bash에서 이 정보를 인쇄하도록 하는 방법이 있습니까?
예, 하지만 루프를 사용하는 것만큼 좋지는 않습니다.
출력의 key=value 부분만 가져오거나 인쇄하는 더 깔끔한 방법이 있습니까?
응, for
루프야. 장점은 외부 프로그램이 필요 없고 간단하며 당황하지 않고 정확한 출력 형식을 쉽게 제어할 수 있다는 것입니다.
declare -p
( )의 출력을 처리하려는 솔루션은 typeset -p
a) 변수 자체에 괄호나 대괄호가 포함될 가능성과 b) declare -p
해당 출력이 셸에 대한 유효한 입력이 되도록 추가해야 하는 인용문을 처리해야 합니다.
예를 들어 b="${a##*(}"
키/값에 여는 대괄호가 포함되어 있으면 확장 시 값의 일부가 소모됩니다. 사용 ##
하고 제거했기 때문입니다.가장 긴접두사. 에 대해서도 마찬가지입니다 c="${b%% )*}"
. 인쇄된 템플릿을 더 정확하게 일치시킬 수는 있지만 declare
참조하는 모든 것을 원하지 않으면 여전히 어려움에 직면하게 됩니다.
꼭 필요한 경우가 아니면 좋지 않아 보입니다.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
루프를 사용하면 for
필요에 따라 출력 형식을 선택하는 것이 더 쉽습니다.
# without quoting
$ for x in "${!array[@]}"; do printf "[%s]=%s\n" "$x" "${array[$x]}" ; done
[def]="foo bar"
[abc]='foobar'
# with quoting
$ for x in "${!array[@]}"; do printf "[%q]=%q\n" "$x" "${array[$x]}" ; done
[def]=\"foo\ bar\"
[abc]=\'foobar\'
거기에서도단순한그렇지 않으면 출력 형식을 변경하십시오(키 주위의 괄호를 제거하고 모든 키/값 쌍을 한 줄에 입력하십시오...). 셸 자체가 아닌 다른 것을 참조해야 하는 경우에도 직접 참조해야 하지만 최소한 작업할 원시 데이터가 있어야 합니다. (키나 값에 줄 바꿈이 있는 경우 일부 인용이 필요할 수 있습니다.)
printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
현재 Bash(내 생각에는 4.4)에서는 printf "%q=%q"
. ( 배열의 극단적인 경우로 인용하고 있지만 key 그렇지 않습니다.)@
%q
for 루프가 작성하기에 너무 피곤해 보인다면 함수로 저장하십시오(여기에서는 인용되지 않음).
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
그런 다음 사용하십시오.
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
인덱스 배열에도 작동합니다.
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
답변2
declare -p array
declare -A array='([a2]="2" [a1]="1" [zz]="Hello World" [b1]="bbb" [f50]="abcd" )'
포크 2개
아마도 이것은:
printf "%s\n" "${!array[@]}"
a2
a1
f50
zz
b1
printf "%s\n" "${array[@]}"
2
1
abcd
Hello World
bbb
printf "%s\n" "${!array[@]}" "${array[@]}" | pr -2t
a2 2
a1 1
f50 abcd
zz Hello World
b1 bbb
포크 3개
아니면 이거:
paste -d= <(printf "%s\n" "${!array[@]}") <(printf "%s\n" "${array[@]}")
a2=2
a1=1
f50=abcd
zz=Hello World
b1=bbb
포크 없음
비교하기 위해서
for i in "${!array[@]}";do printf "%s=%s\n" "$i" "${array[$i]}";done
a2=2
a1=1
f50=abcd
zz=Hello World
b1=bbb
실행 시간 비교
최종 구문은 포크를 사용하지 않으므로 더 빠를 수 있습니다.
time printf "%s\n" "${!array[@]}" "${array[@]}" | pr -2t | wc
5 11 76
real 0m0.005s
user 0m0.000s
sys 0m0.000s
time paste -d= <(printf "%s\n" "${!array[@]}") <(printf "%s\n" "${array[@]}") | wc
5 6 41
real 0m0.008s
user 0m0.000s
sys 0m0.000s
time for i in "${!array[@]}";do printf "%s=%s\n" "$i" "${array[$i]}";done | wc
5 6 41
real 0m0.002s
user 0m0.000s
sys 0m0.001s
그러나 배열이 더 커지면 이 주장은 더 이상 유효하지 않습니다. 소규모 공정에서는 포크를 줄이는 것이 효과적이라면, 대규모 공정에서는 특수 도구를 사용하는 것이 더 효과적입니다.
for i in {a..z}{a..z}{a..z};do array[$i]=$RANDOM;done
time printf "%s\n" "${!array[@]}" "${array[@]}" | pr -2t | wc
17581 35163 292941
real 0m0.150s
user 0m0.124s
sys 0m0.036s
time paste -d= <(printf "%s\n" "${!array[@]}") <(printf "%s\n" "${array[@]}") | wc
17581 17582 169875
real 0m0.140s
user 0m0.000s
sys 0m0.004s
time for i in "${!array[@]}";do printf "%s=%s\n" "$i" "${array[$i]}";done | wc
17581 17582 169875
real 0m0.312s
user 0m0.268s
sys 0m0.076s
논평
이제 그(두 갈래로 갈라진) 다음을 사용하는 솔루션동맹을 맺으세요, 변수에 다음이 포함된 경우새로운 팀. 이 경우 유일한 방법은 for
루프를 실행하는 것입니다.
StackOverflow에 더 안정적이고 자세한 답변이 있습니다.
답변3
K
Bash 5.1에서는 다음과 같은 값을 사용하여 연관 배열을 매우 간단한 방식으로 표시할 수 있습니다 ${arr[@]@K}
.
$ declare -A arr
$ arr=(k1 v1 k2 v2)
$ printf "%s\n" "${arr[@]@K}"
k1 "v1" k2 "v2"
~에서배쉬 5.1 문서:
헤헤. 새로운 "K" 매개변수 변환은 연관 배열을 키-값 쌍으로 표시합니다.
이에 대한 좋은 설명이 있습니다.Bash 참조 매뉴얼 → 3.5.3 쉘 매개변수 확장:
${parameter@operator}
케이
참조된 키-값 쌍의 시퀀스로 인덱스 배열 및 연관 배열의 값을 인쇄하는 것을 제외하고 매개변수 값의 가능한 인용 버전을 생성합니다(배열 참조).
답변4
~부터조판원하는 것을 수행하려면 출력을 편집하면 되지 않습니까?
typeset -p array | sed s/^.*\(// | tr -d ")\'\"" | tr "[" "\n" | sed s/]=/' = '/
주어진
a2 = 2
a1 = 1
b1 = bbb
어디
array='([a2]="2" [a1]="1" [b1]="bbb" )'
장황하지만 형식 지정이 어떻게 작동하는지 쉽게 알 수 있습니다. 점점 더 많은 콘텐츠로 파이프라인을 실행하면 됩니다.sed그리고티주문하다. 당신의 예쁜 인쇄 취향에 맞게 수정해보세요.