bash - Find difference between two variables

7,500

Solution 1

There are many ways...

  • You can use sort, tr unique and paste and $() to execute them and "transform the output in a variable"

    #!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    var3=$(echo " ${var1}, ${var2}" | tr ',' '\n' | sort | uniq -u | paste -sd,)
    echo $var3
    
    1, 2, 5, 6
    

    For each of the previous commands you can read more with e.g. man sort

  • You can transform the variable in bash arrays and work on them (take the follow just as a hint because there is an uncountable number of ways to realize it...)

    #!/bin/bash#!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    # here you transform the variable in array
    IFS=',' read -ra ADDR <<< "$var1"    
    IFS=',' read -ra ADDR2 <<< "$var2"
    # then for each element in the 1st array you search if in the 2nd too
    SEP=""; var3=""
    for i in "${ADDR[@]}"; do
      Found=0
      for j in "${ADDR2[@]}"; do
          [[ "$i" -eq "$j" ]] && Found=1
      done 
      [[ $Found == 0 ]]  && { var3="$var3$SEP$i" ; SEP=", "; }
    done
    # then for each element in the 2nd array you search if in the 1st too
    for j in "${ADDR2[@]}"; do
      Found=0
      for i in "${ADDR[@]}"; do
          [[ "$i" -eq "$j" ]] && Found=1
      done 
      [[ $Found == 0 ]]  && { var3="$var3$SEP$j" ; SEP=", "; }
    done
    echo $var3
    
  • using awk (or to be precise gawk)

    #!/bin/bash
    var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
    var3=$(echo "$var1, $var2" | \
           awk -F ',' '{for (i=1;i<=NF;i++) {A[$i]++;} } 
                    END{ SEP=""; 
                         for (i in A) {if (A[i]==1){
                            printf ("%s%s", SEP,i); SEP=", "} 
                         }
                       }'
          )
    echo $var3
    

Note: the second and the third one outputs are not ordered...


Updated Notes: ...and there is a space before $var1 and $var2 because in your weird (:-)) format there are spaces after the comma (,) so you need special care for all the commands that take only one character as separator... this fix the problem if there was an , 1 in the second string...what are you not able to find with man <command> you can try to find with man bash or with help command...

Ad nauseam:

  • diff style, in the spirit of your attempt... maybe you can search for an output format more cozy (man diff)

    diff --ignore-all-space   \ 
         <(echo "$var1" | tr ',' '\n' ) <(echo "$var2" | tr ',' '\n')\
         | grep -v "^---" | grep -v "^[0-9c0-9]" | tr -d '<||>|| |'  \
         | paste -sd,
    

Solution 2

I don't have time for a full explanation, but:

var1="1, 2, 3, 4"; var2="3, 4, 5, 6"
comm -3 <(grep -oP '\d+' <<<"$var1" | sort) <(grep -oP '\d+' <<<"$var2" | sort) |
  tr -d '\t' |
  paste -sd,
1,2,5,6

Solution 3

Another option:

#!/usr/bin/bash
var1="1, 2, 3, 4"
var2="3, 4, 5, 6"
out=""
for num in `echo $var1,$var2 | tr -d " "| tr "," "\n " | sort | uniq | tr "\n" " "`
do
        if (`grep -v $num <<< "$var1" >/dev/null 2>&1` || `grep -v $num <<< "$var2" >/dev/null 2>&1`)
        then
                out="$out,$num"
        fi
done
echo $out | sed -e 's/,//'

And run

$ ./test.sh 
1,2,5,6
Share:
7,500

Related videos on Youtube

Lejour
Author by

Lejour

Updated on September 18, 2022

Comments

  • Lejour
    Lejour 4 months

    I have two variables: var1="1, 2, 3, 4" and var2="3, 4, 5, 6".
    I'd like to get a new one, var3, containing the differences between $var1 and $var2.
    The expected result should be var3=1, 2, 5, 6.

    I tried diff but the output is not what I wanted:

    diff <(echo "$var1") <(echo "$var2")
    
    1c1
    < 1, 2, 3, 4
    ---
    > 3, 4, 5, 6
    

    Which other solution allows me to have var3 without creating any file?

    • Hastur
      Hastur about 5 years
      Some additional hints... Enjoy SuperUser and bash...
  • Lejour
    Lejour about 5 years
    Thanks! Works perfectly considering special characters as well.
  • Hastur
    Hastur about 5 years
    @Lejour You're welcome... and welcome on SuperUser. Even the other answers seem to work. Try and upvote the answers you find correct and useful. Choose the one you prefer as the answer for your question and enjoy the site.