【问题标题】:Select a specific line of an array in a for loop在 for 循环中选择数组的特定行
【发布时间】:2020-06-24 15:50:47
【问题描述】:

我有一个包含多行的数组,我想在 for 循环中选择数组的特定行。然后在for循环中使用所选行中的数据进行一些分析。

ARRAY=(A1,A2 
B1,B2 
C1,C2)

当我应用以下代码时,我可以将“B1”分配给 Trait1,将“B2”分配给 Trait2。这也适用于 j=1 或 j=3。

j=2
echo ${ARRAY[$j-1]}
Trait1="$(echo ${ARRAY[$j-1]} | cut -d',' -f1)"
Trait2="$(echo ${ARRAY[$j-1]} | cut -d',' -f2)"
echo $Trait1
echo $Trait2

最后,我想把上面的代码放在一个 for 循环中。但这失败了。

nLine=3
for j in $(eval echo "{1..$nLine}")
do
    Trait1="$(echo ${ARRAY[$j-1]} | cut -d',' -f1)"
    Trait2="$(echo ${ARRAY[$j-1]} | cut -d',' -f2)"
    echo $Trait1
    echo $Trait2
done

-bash: 1 2 3-1: syntax error in expression (error token is "2 3-1")
-bash: 1 2 3-1: syntax error in expression (error token is "2 3-1")

谢谢。

【问题讨论】:

  • 为什么不只是${ARRAY[j]}${ARRAY[$j]}?它们是“线”,顺便说一下,它们是独立的元素,所以${ARRAY[0]}A!,A2${ARRAY[1]}B1,B2,等等。
  • 当你访问一个没有索引的数组时,它相当于${ARRAY[0]}
  • 这里没有shell分词的换行符
  • 谢谢大家。我可以在 for 循环之外使用数组索引运算符。但是,当我按照修改后的问题中的说明将相同的代码放入循环时出现错误。
  • 更新/编辑的for循环代码块对我有用(生成A1\nA2\nB1\nB2\nC1\nC2);你运行的是什么版本的bash? (bash --version)

标签: arrays bash for-loop


【解决方案1】:

保持当前的代码设计我可能想使用parameter expansion 将数组元素分成两个组件...

数据设置:

$ ARRAY=(A1,A2
B1,B2
C1,C2)
$ typeset -p ARRAY
declare -a ARRAY=([0]="A1,A2" [1]="B1,B2" [2]="C1,C2")

参数扩展快速演示将数组元素分解为多个部分:

$ x=${ARRAY[0]}
$ echo ${x}
A1,A2
$ echo ${x%,*}
A1
$ echo ${x#*,}
A2

更新 PO 的 for 循环以使用参数扩展,并将 eval/echo/j-1 替换为更易于阅读的内容:

nLine=3
for (( j=0 ; j<nLine ; j++ ))
do
    Trait1="${ARRAY[${j}]%,*}"
    Trait2="${ARRAY[${j}]#*,}"
    echo "${Trait1}"
    echo "${Trait2}"
done

生成输出:

A1
A2
B1
B2
C1
C2

【讨论】:

  • 谢谢。这很有帮助。
【解决方案2】:

你使用它的方式,你应该有一个单一的字符串,而不是一个数组。

ARRAY='A1,A2 
B1,B2 
C1,C2'

那么当你用它作为sed的here-string输入时,它会接收多行输入,你可以用${j}p选择你想要的行。

正如 cmets 中提到的,这似乎是一种访问数组元素的复杂方式。您可以简单地使用 shell 的内置数组索引运算符。

【讨论】:

    【解决方案3】:

    数组赋值

    ARRAY=(A1,A2
    B1,B2
    C1,C2)
    

    ARRAY=(A1,A2 B1,B2 C1,C2)
    

    是等价的,都定义了一个包含 3 个元素的数组:A1,A2B1,B2C1,C2。空格、制表符和换行符用于分隔复合赋值中的数组元素。

    for 循环可用于遍历数组:

    #  "${ARRAY[@]}" expands each element of ARRAY to a separate word
    for elm in "${ARRAY[@]}"; do
        # The value of the array element accessed is "$elm"
    done
    

    或者,使用for 循环的替代形式:

    #  ${#ARRAY[*]} expands to the number of elements in the ARRAY
    for ((j = 0; j < ${#ARRAY[*]}; ++j)); do
        # Array element can be referenced using ${ARRAY[j]}
    done
    

    假设索引之间没有间隙(bash 允许数组带有“孔”)。

    Here 字符串here 文档的变体,以及带有IFS 变量的内置read 可用于解析数组的元素:

    IFS=, read Trait1 Trait2 <<< ${ARRAY[j]}
    

    这里IFS 与值, 一起使用,当有, 时,将数组元素切割成Trait1Trait2

    因此,演示所有这些的示例程序可能是:

    #!/bin/bash
    
    ARRAY=(A1,A2 
    B1,B2 
    C1,C2)
    
    for elem in "${ARRAY[@]}"; do
        IFS=, read Trait1 Trait2 <<< $elem
        printf "%s\n%s\n" "$Trait1" "$Trait2"
    done
    

    或者,

    #!/bin/bash
    
    ARRAY=(A1,A2 
    B1,B2 
    C1,C2)
    
    for ((j = 0; j < ${#ARRAY[*]}; ++j)); do
        IFS=, read Trait1 Trait2 <<< ${ARRAY[j]}
        printf "%s\n%s\n" "$Trait1" "$Trait2"
    done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多