bashcomm

How do I see if the output of one command is in the output of another?


I have two commands. The first, when stored in a script variable, gives output like this:

one two three four five

The second also gives a list, but some of the items may be missing that were in the first command:

one three five

I want my script to do something if an item is in the first command but not the second. None of the items will have spaces (they tend to be kabab-format). How can I do this in Bash?


Solution

  • One approach using the current variables, and relying on the fact that individual values do not contain embedded white space:

    $ var1='one two three four five'
    $ var2='one three five'
    $ comm -23 <(printf "%s\n" ${var1} | sort) <(printf "%s\n" ${var2} | sort)
    four
    two
    

    NOTE: do not wrap the ${var1} and ${var2} references in double quotes, ie, we want word splitting to occur when feeding the printf calls


    Another idea using an associative array to track unique values:

    var1='one two three four five'
    var2='one three five'
    
    unset      arr
    declare -A arr
    
    for f in ${var1}          # use ${var1} values as indices for arr[]
    do
        arr[${f}]=1           # '1' has no meaning other than to fill requirement of assigning a value in order to create the array entry
    done
    
    for f in ${var2}          # delete ${var2} indices from arr[]
    do
        unset arr[${f}]
    done
    
    
    for i in "${!arr[@]}"     # display arr[] indices that remain
    do
        echo "${i}"
    done
    
    # one-liners (sans comments)
    
    for f in ${var1}; do arr[${f}]=1; done
    for f in ${var2}; do unset arr[${f}]; done
    for i in "${!arr[@]}"; do echo "${i}"; done
    

    This generates:

    two
    four
    

    NOTES: