首页 > 解决方案 > 使用 BASH 在一行上输出满足条件的数组的所有元素

问题描述

以下将在 BASH 脚本中实现。我可以访问我认为是 bash 脚本中常用的其他“设备”,例如 sed、awk、bc、dc 等。我有一个数组,其元素是字符串。元素要么是“无”,要么是名称。这个问题分为两部分。第一个以尽可能少的背景讨论问题的最简单形式。这就是我认为所需要的。第二部分几乎完全是关于我一般尝试做的事情的背景,可能有用,但我认为不一定需要。

第 1 部分:简短版

我有一个字符串数组

这个数组的一个例子是

array=('none' 'none' 'name1' 'none' 'name2' 'none' 'name3' 'none' 'name4')

在我的问题中,数组更长。我想搜索特定元素是“无”还是“名称#”(即,不是“无”)。我需要的是从元素 i 开始,然后检查每个第 n 个元素,看看它是“无”还是“名称#”,并在一行上打印所有“名称#”的元素

对于此示例,这意味着如果我想从元素 2(数组从 0 开始)开始输出,然后检查之后的每个第三个元素:我的输出将是name1 name4

如果我从元素 1 开始,那么我的输出将是name3

我对管道的理解不够好,无法与条件相呼应(实际上有两个条件,第一个是元素的周期范围,第二个是名称与无条件)。

第 2 部分:更长的版本(不是必需的)

我正在运行一个调用程序的双循环。每隔一段时间,输出不是我想要的,所以我标记了运行名称和我不喜欢的运行的一部分。我设置了这个标准,它在名称中保存了“i”“j”,所以我知道故障发生在哪里。

由于 bash 处理数组而不是矩阵,因此我将这些失败状态保存在一个 i * j 长的数组中。这就是为什么我需要访问某个部分。如果每次运行有 3 个部分,那么在后期分析中,对于该运行,我会搜索与该循环对应的元素。即,如果有 3 个运行,每个运行 3 个部分,那么在我的数组元素中,0-2 是运行 1,3-5 是运行 2,6-8 是运行 3。这对应于我上面显示的数组。

在本例中,每次运行都有一个部分 1、2 和 3,或者在 bash 语法中是一个部分 0,1 和 2。(即元素 0,3,6 分别是上述数组中运行 0 1 2 的第一部分,1 ,4,7 分别是运行 0,1,2 的第二部分,元素 2,5,8 分别是运行 0,1,2 的第三部分)。对于每组零件,我想打印出与那些不是“无”的零件相对应的所有元素

这是该过程的虚拟代码片段(这很好用,问题与之后的分析后部分有关)

k=0
for ((i=0 ; i<$NRuns ; i++)); do
    for ((j=0 ; j<$NPartsPerRun ; j++)); do
        k=$((k + 1))
        #PSEUDO CODE HERE not actual bash
        call program
        if "program output bad" ; then
            array[$k]=$Runname
        else
            echo "Thanks for taking the time to look at my problem"
        fi
    done
done

现在进行后期分析,我想知道运行失败的给定部分。即对于给定的“j”,失败的“i”的运行名是什么

后分析(和我的问题。代码是传达这个想法的遗憾尝试,它实际上更像是一个伪代码,它不是 bash)

for ((i=0 ; i<$NPartsPerRun ; i++)); do
    #PSEUDO CODE HERE not actual bash
    #first element to check is $i, then check every Xth element
        if ${array[$i]} || ${array[$(i+X)]} etc.. != 'none' echo "element names that pass condition test"
        fi
    done
done   

标签: arraysbash

解决方案


如果我正确理解了这个问题,您可以使用关联数组来模拟矩阵,并使您的代码更具可读性:

declare -A matrix=()

# save runs into the matrix
for ((i=0; i<n_runs; i++)); do
    for ((j=0; j<n_parts; j++)); do
        [[ $(program) = bad ]] && matrix[$i,$j]=$name
    done
done

# print unsuccessful runs for a given part
part=2 runs=

for ((i=0; i<n_runs; i++)); do
    [[ ${matrix[$i,$part]} ]] && runs+="${matrix[$i,$part]} "
done

printf '%s\n' "${runs% }"

推荐阅读