Python has a "set" type which contains unique objects. Does Bash have something equivalent?
I want to keep adding elements to such a bash "set" and never have duplicates.
Python has a "set" type which contains unique objects. Does Bash have something equivalent?
I want to keep adding elements to such a bash "set" and never have duplicates.
Bash 4.0 has associative arrays, which can be used to build sets.
Here's an article that discusses them (it was the first Google hit for "bash associative arrays").
(Personally, I'd just use something other than bash, probably Perl.)
some_dups=(aa aa b b c)
uniques=($(for v in "${some_dups[@]}"; do echo "$v";done| sort| uniq| xargs))
echo "${uniques[@]}"
gives
aa b c
also in bash 3, where no associative arrays are available
After some googling I found a nice bash implementation at http://www.catonmat.net/blog/set-operations-in-unix-shell-simplified/. It has all the usual set operators in multiple ways, and even a printable pdf cheatsheet.
I've used associative arrays though, it's much more readable.
Declare a setA
associative array variable:
$ declare -A setA
Or declare and add the initial members at the same time:
$ declare -A setA=([memberA]=1 [memberB]=1)
Add a member to the set:
$ setA[memberC]=1
Test for membership:
$ [ -n "${setA[memberC]}" ] && echo in set || echo not in set
in set
$ [ -n "${setA[memberD]}" ] && echo in set || echo not in set
not in set
List members (space separated):
$ echo "${!setA[@]}"
memberA memberC memberB
or (newline separated):
$ printf '%s\n' "${!setA[@]}"
memberB
memberC
memberA
Iterate through members:
$ for m in "${!setA[@]}"; do echo "$m"; done
memberB
memberC
memberA
Cardinality (number of members in the set):
$ echo ${#setA[@]}
3
Remove a member:
$ unset setA[memberC]
Use quotes to add members with spaces in their name:
$ setA["member with space"]=1
And it's possible to use variables as members too:
$ read -r str
$ setA["$str"]=1