Bash 在数组上循环,打印索引和值

Bash 在数组上循环,打印索引和值,bash,Bash,我想这样做: foo=( ) foo[0]="bar" foo[35]="baz" for((i=0;i<${#foo[@]};i++)) do echo "$i: ${foo[$i]}" done # Output: # 0: bar # 1: 但这里我不知道索引值 我知道你可以这样做 foo=( ) foo[0]="bar" foo[35]="baz" declare -p foo # Output: # declare -a foo='([0]="bar" [35]="b

我想这样做:

foo=( )
foo[0]="bar"
foo[35]="baz"
for((i=0;i<${#foo[@]};i++))
do
    echo "$i: ${foo[$i]}"
done
# Output:
# 0: bar
# 1: 
但这里我不知道索引值

我知道你可以这样做

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

但是,你不能用另一种方法吗?

你会发现数组键带有
“${!foo[@]}”
(),因此:


这意味着索引将位于
$i
中,而元素本身必须通过
${foo[$i]}

访问。您可以始终使用迭代参数:

ITER=0
对于${FOO[@]}中的I
做
echo${I}${ITER}
ITER=$(expr$ITER+1)
完成

在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.
在Bash3中,这是有效的(在zsh中也有效):

转储数组的简单单线技巧 我用空格添加了一个值:

foo=()
foo[12]="bar"
foo[42]="foo bar baz"
foo[35]="baz"
一、 对于快速转储数组或关联数组,我使用

此单行命令:

paste <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
解释
  • printf“%s\n”${!foo[@]}“
    将打印由换行符分隔的所有键
  • printf“%s\n”${foo[@]}
    将打印所有由换行符分隔的值

  • 粘贴重要注释,虽然可以粘贴,但以空格分隔的单词列表不是数组。像这样包装它以将其转换为数组。
    [@]
    和双引号的使用意味着它不是一个“以空格分隔的单词列表”。您可以得到实际数组键的列表,即使单个键包含空格。@glennjackman您可以进一步解释一下吗
    使用[@]和双引号意味着它不是一个“以空格分隔的单词列表”
    “${foo[@]}”
    接受(数组)变量
    foo
    ,并将其扩展为一个数组,保持其元素的标识,即不在空白处拆分它们。如果
    foo=(x'y z')
    ,则
    f“${foo[@]}”
    使用两个参数调用
    f
    x
    'y z'
    。元数据查询,如
    “${!foo[@]}”
    “${#foo[@]}”
    类似地将
    foo
    作为数组进行处理。答案正确,但这是难以理解的。有帮助的解释是:“
    ”${!foo[@]}“
    是数组中设置的所有索引的列表”。您的答案当然值得一点解释。请参阅。评论将有助于创建可搜索的内容。虽然此代码片段可能会解决此问题,但确实有助于提高您文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。还请尽量不要用解释性注释挤满你的代码,这会降低代码和解释的可读性!我喜欢简洁的回答和策略。如果有人想知道这是bash,战略是什么,你只需要自己跟踪数组索引。
    ((ITER++)
    在现代bash中,为什么是后期增量?您只希望值递增,因此(++ITER))更直接地表示您希望做什么……不,不是“总是”。散列可以有“洞”,这意味着并非所有数字都是索引。在您的示例中${ITER}并不总是${I}的索引。这是错误的!内部循环是无用的,可能导致错误的结果!我对
    printf”%q\n“${var[@]}”
    newline的投票是我的问题!
    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
    
    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.
    
    map=( )
    map+=("0:bar")
    map+=("35:baz")
    
    for keyvalue in "${map[@]}" ; do
        key=${keyvalue%%:*}
        value=${keyvalue#*:}
        echo "key: $key, value $value."
    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
    
    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 -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'
    
    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
    
              %q     causes  printf  to output the corresponding argument in a
                     format that can be reused as shell input.