Sunday, March 13, 2022

[SOLVED] Conditional print based on array content in bash or awk

Issue

I have an input file with following contents:

SS SC
a 1
b 2
d 5
f 7

I have an input bash array as follow:

echo "${input[*]}"
a b c d e f

I need to create an output to:

1. print the all elements of the array in 1st column
2. In second column, I need to print 0 or 1, based on the presence of the element.

To explain this, in the input array called input, I have a,b,c,d,e,f. Now a is present in input file, so the output should be a 1, whereas c is missing in the input file, so the output should be c 0 in the output.

Eg: Expected result:

SS RESULT
a 1
b 1
c 0
d 1
e 0
f 1

Tried, to split the bash array in an attempt to iterate over it, but its printing for each line(the way awk works), its getting too difficult to handle. awk -v par="${input[*]}" 'BEGIN{ n = split(par, a, " ")} {for(i=0;i<=n;i++){printf "%s\n", a[i]}}' input

I am able(missing header) to do this with bash for loop and some grep: But hoping awk would be shorter, as I need to put this in a yaml file so need to keep it short.

for item in ${input[@]};do 
     if ! grep -qE "^${item}" input ;then
        echo "$item 0";
     else 
        echo "$item 1";
     fi;
done

a 1
b 1
c 0
d 1
e 0
f 1

Solution

Using awk to store the values in the first column of the file in an associative array and then see if the elements of the array exist in it:

#!/usr/bin/env bash

input=(a b c d e f)

awk 'BEGIN { print "SS", "RESULT" }
     FNR == NR { vals[$1] = 1; next }
     { print $0, $0 in vals }
    ' input.txt <(printf "%s\n" "${input[@]}")

Or doing the the same thing in pure bash:

#!/usr/bin/env bash

input=(a b c d e f)

declare -A vals
while read -r v _; do
    vals[$v]=1
done < input.txt

echo "SS RESULT"
for v in "${input[@]}"; do
    if [[ -v vals[$v] ]]; then
        printf "%s 1\n" "$v"
    else
        printf "%s 0\n" "$v"
    fi
done


Answered By - Shawn
Answer Checked By - David Goodson (WPSolving Volunteer)