[bash] 배열을 반복하여 인덱스와 값을 모두 인쇄

나는 이런 식으로하고 싶다 :

foo=( )
foo[0]="bar"
foo[35]="baz"
for((i=0;i<${#foo[@]};i++))
do
    echo "$i: ${foo[$i]}"
done
# Output:
# 0: bar
# 1: 

그런 다음 for를 사용하여 반복하려고했습니다.

foo=( )
foo[0]="bar"
foo[35]="baz"
for i in ${foo[@]}
do
    echo "?: $i"
done
# Output:
# ?: bar
# ?: naz

그러나 여기서는 색인 값을 모릅니다.

나는 네가 다음과 같은 것을 할 수 있다는 것을 안다

foo=( )
foo[0]="bar"
foo[35]="baz"
declare -p foo
# Output:
# declare -a foo='([0]="bar" [35]="baz")'

그러나 다른 방법으로는 할 수 없습니까?



답변

"${!foo[@]}"( reference )가 있는 배열 키를 찾을 수 있습니다.

for i in "${!foo[@]}"; do
  printf "%s\t%s\n" "$i" "${foo[$i]}"
done

$i, 요소 자체를 통해 액세스 해야하는 동안 인덱스가 포함 됩니다.${foo[$i]}


답변

항상 반복 매개 변수를 사용할 수 있습니다.

ITER=0
for I in ${FOO[@]}
do
    echo ${I} ${ITER}
    ITER=$(expr $ITER + 1)
done


답변

INDEX=0
for i in $list; do
    echo ${INDEX}_$i
    let INDEX=${INDEX}+1
done


답변

bash 4에서는 연관 배열을 사용할 수 있습니다.

declare -A foo
foo[0]="bar"
foo[35]="baz"
for key in "${!foo[@]}"
do
    echo "key: $key, value: ${foo[$key]}"
done

# output
# $ key: 0, value bar.
# $ key: 35, value baz.

bash 3에서 이것은 작동합니다 (zsh에서도 작동합니다).

map=( )
map+=("0:bar")
map+=("35:baz")

for keyvalue in "${map[@]}" ; do
    key=${keyvalue%%:*}
    value=${keyvalue#*:}
    echo "key: $key, value $value."
done


답변

users=("kamal" "jamal" "rahim" "karim" "sadia")
index=()
t=-1

for i in ${users[@]}; do
  t=$(( t + 1 ))
  if [ $t -eq 0 ]; then
    for j in ${!users[@]}; do
      index[$j]=$j
    done
  fi
  echo "${index[$t]} is $i"
done


답변

배열 덤프를위한 간단한 한 줄 트릭

공백으로 하나의 값을 추가했습니다.

foo=()
foo[12]="bar"
foo[42]="foo bar baz"
foo[35]="baz"

나는 빨리 덤프 내가 사용하는 배열 또는 연관 배열

이 한 줄 명령 :

paste <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")

렌더링합니다 :

12  bar
35  baz
42  foo bar baz

설명

  • printf "%s\n" "${!foo[@]}"개행으로 구분 된 모든 를 인쇄합니다 .
  • printf "%s\n" "${foo[@]}"개행으로 구분 된 모든 을 인쇄합니다 .
  • paste <(cmd1) <(cmd2)출력 병합 것 cmd1cmd2라인 씩.

튜닝

-d스위치 로 조정할 수 있습니다 .

paste -d : <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
12:bar
35:baz
42:foo bar baz

또는:

paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[35]='baz'
foo[42]='foo bar baz'

연관 배열은 동일하게 작동합니다.

declare -A bar=([foo]=snoopy [bar]=nice [baz]=cool [foo bar]='Hello world!')
paste -d = <(printf "bar[%s]\n" "${!bar[@]}") <(printf '"%s"\n' "${bar[@]}")
bar[foo bar]="Hello world!"
bar[foo]="snoopy"
bar[bar]="nice"
bar[baz]="cool"

바꿈 또는 특수 문자 문제

불행히도, 더 이상 작동하지 않는 조건이 하나 이상 있습니다. 변수에 줄 바꿈이 포함될 때 :

foo[17]=$'There is one\nnewline'

명령 paste은 라인별로 병합되므로 출력이 잘못됩니다.

paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[17]='There is one
foo[35]=newline'
foo[42]='baz'
='foo bar baz'

이 작업을 위해 두 번째 명령 %q대신 따옴표를 사용할 수 있습니다 .%sprintf

paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "%q\n" "${foo[@]}")

완벽하게 렌더링됩니다 :

foo[12]=bar
foo[17]=$'There is one\nnewline'
foo[35]=baz
foo[42]=foo\ bar\ baz

보낸 사람 man bash:

          %q     causes  printf  to output the corresponding argument in a
                 format that can be reused as shell input.

답변