首页 > 解决方案 > 循环遍历数组并基于一列值,连接另一列值

问题描述

以下是我在数组中的值

10.106.86.93,A1,3
10.106.86.93,A2,3
10.106.86.93,A2,3
10.106.86.93,A3,3
10.106.86.93,A3,3
10.106.86.93,A4,3

需要遍历这个,如果最后一个值等于 3 则必须合并第二列的值

例如

10.106.86.93  A1,A2,A2,A3,A3,A4  3

正在尝试一些 for 循环,但没有正确使用

while read -r line
do
    StatusValue= $line | awk -F, '{print $NF}'
    if [[${StatusValue} == "3"}]] then
       echo $line | awk -F,'{print $2}'
    fi

done <<< ${Dell_Data_Status_3}

在这里,我尝试在状态为 3 时打印该行的第二个值

但无法获得输出。

错误 :

./SortFile.sh: line 30: syntax error near unexpected token `fi'
./SortFile.sh: line 30: `    fi'

请让我知道这里有什么问题

标签: bashawksed

解决方案


让我们从一个简单的 bash 语法开始:

以下是我在数组中的值

好的,所以我们有一个 bash 数组:

arr=(
10.106.86.93,A1,3
10.106.86.93,A2,3
10.106.86.93,A2,3
10.106.86.93,A3,3
10.106.86.93,A3,3
10.106.86.93,A4,3
)

需要循环这个

行。首先,我们需要将数组输出为换行符分隔列表。以下将输出数组:

$ printf "%s\n" "${arr[@]}"

然后我们需要读取数组元素并在逗号分隔符上拆分它们。我们IFS使用变量来控制 bash 拆分元素的字符:

printf "%s\n" "${arr[@]}" |
while IFS=, read -r ip A num; do
     : # TODO body
done

行。现在我们可以检查第三列的值,如果它匹配 3,则输出第三列:

printf "%s\n" "${arr[@]}" |
while IFS=, read -r ip A num; do
     if [ "$num" = 3 ]; then
          echo "$A"
     fi
done

请注意,每个空格都很重要。您的代码中的 theif [[${StatusValue} == "3"}]] then非常无效 - 您需要在 and 之间有一个空格,[[并且在and之间${..有一个空格,这是无效的。请记住,您使用键盘与计算机交谈,仅此而已 - 每次击键都很重要。"3"]]}

现在最困难的部分:

如果最后一个值等于 3 则必须合并第二列的值

好吧,这可以通过awk脚本简单快速地完成。我们需要做的是创建地图。我们需要将第三列值映射到其他两列。

但是让我们做一个简单、愚蠢且非常非常缓慢的方法:

  1. 识别第三列中的唯一值
  2. 对于第三列中的每个唯一值
    1. 获取具有此值的所有行作为第三列
    2. 从任何行中获取第一列
    3. 从过滤的行中提取第二列并将它们连接起来
    4. 输出一行

# just to have the array as a string
arrstr=$(printf "%s\n" "${arr[@]}")

# cut only the third column and get unique values
<<<"$arrstr" cut -d, -f3  | sort -u |
# for each unique third column value
while read -r num; do
    # get the columns that have that value as the third column
    filtered=$(<<<"$arrstr" awk -vIFS=, -vOFS=, '$3 = '"$num")
    # get the values of the second field only
    # substitute newline for comma
    # remove the trailing comma
    second_field_sum=$(<<<"$filtered" cut -d, -f2 | tr '\n' ',' | sed 's/,$//')
    # get the value of the first field (from the first line)
    ip=$(<<<"$filtered" head -n1 | cut -d, -f1)
    # output
    printf "%s %s %s\n" "$ip" "$second_field_sum" "$num"
done

请在shellcheck.net上检查您的脚本是否有错误。大多数初学者错误(缺少引号、拼写错误、错误的重定向、if语法错误)很容易通过听 shellcheck 消息来修复。


推荐阅读