How can I get unique values from an array in Bash?

前端 未结 14 1126
-上瘾入骨i
-上瘾入骨i 2020-11-27 12:50

I\'ve got almost the same question as here.

I have an array which contains aa ab aa ac aa ad, etc. Now I want to select all unique elements from this ar

14条回答
  •  攒了一身酷
    2020-11-27 13:15

    If your array elements have white space or any other shell special character (and can you be sure they don't?) then to capture those first of all (and you should just always do this) express your array in double quotes! e.g. "${a[@]}". Bash will literally interpret this as "each array element in a separate argument". Within bash this simply always works, always.

    Then, to get a sorted (and unique) array, we have to convert it to a format sort understands and be able to convert it back into bash array elements. This is the best I've come up with:

    eval a=($(printf "%q\n" "${a[@]}" | sort -u))
    

    Unfortunately, this fails in the special case of the empty array, turning the empty array into an array of 1 empty element (because printf had 0 arguments but still prints as though it had one empty argument - see explanation). So you have to catch that in an if or something.

    Explanation: The %q format for printf "shell escapes" the printed argument, in just such a way as bash can recover in something like eval! Because each element is printed shell escaped on it's own line, the only separator between elements is the newline, and the array assignment takes each line as an element, parsing the escaped values into literal text.

    e.g.

    > a=("foo bar" baz)
    > printf "%q\n" "${a[@]}"
    'foo bar'
    baz
    > printf "%q\n"
    ''
    

    The eval is necessary to strip the escaping off each value going back into the array.

提交回复
热议问题