在一行上输出使用BASH满足条件的数组的所有元素

时间:2021-09-18 15:41:46

The following is to be implemented in a BASH script. I have access to what I think are other "devices" commonly used in bash scripts such as sed, awk, bc, dc etc. I have an array whose elements are strings. The elements are either "none" or a name. This question is in 2 parts. The first goes over the simplest form of the problem with as little background as possible. It is all that is needed I think. The second part is almost entirely background on what I am trying to do in general and may be useful, but I do not think is needed necessarily.

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

Part 1: SHORT VERSION

I have an array of strings

我有一个字符串数组

An example of this array is

这个数组的一个例子是

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

In my problem the array is much longer. I would like to search if specific elements are 'none' or 'name#' (i.e., not 'none'). AND What I need is to start at element i and check every nth element after that to see if it is 'none' or 'name#' and print all elements that are 'name#' on one line

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

For this example that means if I want to output starting from say element 2 (array starts at 0) and then checking every 3rd element after that: my output for this would be name1 name4

对于这个例子,这意味着我想从say元素2开始输出(数组从0开始),然后检查后面的每个第3个元素:我的输出为name1 name4

if I had started at element 1 then my output would have been name3

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

I do not understand piping sufficiently well to be able to echo with a condition (2 conditions really, the first being the periodic range of elements, the second the name vs none criteria).

我不太了解管道能够回应条件(实际上是2个条件,第一个是元素的周期性范围,第二个是名称与无条件)。

Part 2: LONGER VERSION (NOT NECCESSARY)

I am running a double do loop that calls a program. every once in a while the output is not what I want, so I flag the run name and part of that run that I didn't like. I have this criteria set up it saves the "i" "j" in the name so I know where the failure occurred.

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

Since bash does arrays and not matrices, I save these failed states in an array that is i * j long. This is why I need to access a certain section. If each run has 3 parts, then in post analysis, for that run, I search the elements that correspond to that loop. i.e. if there are 3 runs with 3 parts in each, then in my array elements 0-2 are run 1, 3-5 are run 2, and 6-8 are run 3. This corresponds to the array I have shown above.

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

each run has a part 1, 2 and 3 in this example, or in bash syntax a part 0,1 and 2. (i.e. elements 0,3,6 is the first parts of runs 0 1 2 respectively in the above array, 1,4,7 is the second parts of runs 0,1,2 respectively, and elements 2,5,8 are the 3rd parts of runs 0,1,2 respectively). For each set of parts I want to print out all elements corresponding to those parts that are not 'none'

每次运行在本例中都有第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的第3部分)。对于每组零件,我想打印出与那些不是“无”的零件相对应的所有元素

Here is a dummy code snippet of the process (and this works fine, the question pertains to the post analysis part after)

这是一个过程的虚拟代码片段(这个工作正常,问题属于后分析部分)

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

Now for post analysis, I want to know for a given part, which runs failed. i.e for a given "j" what were the runnames of the "i's" that failed

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

Post analysis (and my issue. The code is a sorry attempt to convey the idea, it is really more of a pseudo code, it is not bash)

发布分析(和我的问题。代码是一个遗憾的尝试传达的想法,它真的更多的是伪代码,它不是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   

2 个解决方案

#1


1  

I don't know if it solves your problem but I think that it would be something close to this.

我不知道它是否解决了你的问题,但我认为这将是接近这一点。

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

echo "array size = ${#array[@]}"
echo "step = $step"

for ((i= 0; i < step; i += 1)); do
    echo -ne  "i = $i: [ "
    for ((j = i; j < ${#array[@]}; j += step)); do
        if [[ "${array[$j]}" != "none" ]]; then
            echo -n "${array[$j]} "
        fi
    done
    echo "]"
done

This will output:

这将输出:

array size = 9
step = 3
i = 0: [ name3 ]
i = 1: [ name2 ]
i = 2: [ name1 name4 ]

This works by using a nested loop to check for the indexes of the form $i + n * $step.

这通过使用嵌套循环来检查$ i + n * $步骤形式的索引。

You could, of course, change the way it's printing the values to suit your use case. I hope it answers at least the short version of your question!

当然,您可以更改打印值以适合您的用例的方式。我希望它至少回答你的问题的简短版本!

#2


2  

If I understood the question correctly, you could emulate a matrix with an associative array and make your code much more readable:

如果我正确理解了这个问题,你可以模拟一个带有关联数组的矩阵,让你的代码更具可读性:

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% }"

#1


1  

I don't know if it solves your problem but I think that it would be something close to this.

我不知道它是否解决了你的问题,但我认为这将是接近这一点。

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

echo "array size = ${#array[@]}"
echo "step = $step"

for ((i= 0; i < step; i += 1)); do
    echo -ne  "i = $i: [ "
    for ((j = i; j < ${#array[@]}; j += step)); do
        if [[ "${array[$j]}" != "none" ]]; then
            echo -n "${array[$j]} "
        fi
    done
    echo "]"
done

This will output:

这将输出:

array size = 9
step = 3
i = 0: [ name3 ]
i = 1: [ name2 ]
i = 2: [ name1 name4 ]

This works by using a nested loop to check for the indexes of the form $i + n * $step.

这通过使用嵌套循环来检查$ i + n * $步骤形式的索引。

You could, of course, change the way it's printing the values to suit your use case. I hope it answers at least the short version of your question!

当然,您可以更改打印值以适合您的用例的方式。我希望它至少回答你的问题的简短版本!

#2


2  

If I understood the question correctly, you could emulate a matrix with an associative array and make your code much more readable:

如果我正确理解了这个问题,你可以模拟一个带有关联数组的矩阵,让你的代码更具可读性:

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% }"