Bashで配列の積集合・差集合を求める

Bashで文字列の差集合を求める関数を実装しました。
結構つまりながら実装したのでブログに書いておきます。

考え方

  1. 集合Aと集合Bの積集合(共通要素の集合)を求める。
  2. 集合Aと「1. 集合Aと集合Bの積集合」で重複していない要素を求める。

実装

except() {
  # 文字列を集合と見たときの差集合`a - b`を返す
  local a b intersection difference
  a=$1
  b=$2

  intersection=($(for item in ${a} ${b}; do echo "$item"; done | sort | uniq -d))
  difference=($(for item in ${a} ${intersection[@]}; do echo "$item"; done | sort | uniq -u))
  echo "${difference[@]}"
}

出力はこうなる。

except "a b c d" "c d e"  #==> a b
except "( "b" "c" "d" "a" )" "( "c" "e" )"  #==> a b d

array1=( "a" "b" "c" "d" "e" )
array2=( "a" "d" )
_except "${array1[*]}" "${array2[*]}"  #==> b c e

詰まったところ

  • Bash慣れてなくて、文字列なのか、配列なのかを混同していた。
  • [@][*]が各要素をつなげるのか、別の要素にするのか(ちょっとまだよく分かっていない)

もっと簡単にできるよということがあれば、コメントお願いします。