Bash의 문자열/배열에서 고유 요소 배열을 만드는 방법은 무엇입니까?

Bash의 문자열/배열에서 고유 요소 배열을 만드는 방법은 무엇입니까?

문자열 "1 2 3 2 1" 또는 배열 [1,2,3,2,1]이 있는 경우 고유한 값을 어떻게 선택합니까?

"1 2 3 2 1" produces "1 2 3" 

또는

[1,2,3,2,1] produces [1,2,3]

uniq와 유사하지만 uniq는 라인 내의 패턴이 아닌 전체 라인에 적용되는 것 같습니다.

답변1

zsh를 사용하는 경우:

$ array=(1 2 3 2 1)
$ echo ${(u)array[@]}
1 2 3

또는 ( KSH_ARRAYS옵션이 설정되지 않은 경우)

$ echo ${(u)array}
1 2 3

답변2

GNU 사용 awk(원래 순서도 유지됨)

printf '%s\n' "1 2 3 2 1" | awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}'
1 2 3 

read배열 로bash

read -ra arr<<<$(printf '%s\n' "1 2 3 2 1" |
 awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}')
printf "%s\n"  "${arr[@]}"
1
2
3

답변3

bash내장된 연산자가 없기 때문에 임의의 값을 가진 배열의 경우 이는 매우 까다롭습니다 .

bash그러나 변수에 NUL 문자를 저장하는 것을 지원하지 않으므로 이를 활용하여 다른 명령에 전달할 수 있습니다.

다음 zsh과 동일:

new_array=("${(@u}array}")

최근 GNU 시스템에서는 다음과 같을 수 있습니다:

eval "new_array=($(
  printf "%s\0" "${array[@]}" |
    LC_ALL=C sort -zu |
    xargs -r0 bash -c 'printf "%q\n" "$@"' sh
  ))"

또는 최신 버전을 사용 bash하고 모든 배열 요소가 비어 있지 않다고 가정하면 연관 배열을 사용할 수 있습니다.

unset hash
typeset -A hash
for i in "${array[@]}"; do
  hash[$i]=
done
new_array=("${!hash[@]}")

bash 4.4 이상 및 GNU 사용 sort:

readarray -td '' new_array < <(
  printf '%s\0' "${array[@]}" | LC_ALL=C sort -zu)

이러한 다양한 솔루션에서는 요소의 순서가 동일하지 않습니다.

그리고 tcsh:

set -f new_array = ($array:q)

지킬 것이다에프첫 번째 요소( a b a=> )는 확장 플래그 a b처럼 작동합니다 .zsh(u)

set -l new_array = ($array:q)

마지막 항목( a b a=> b a)이 유지됩니다. 그러나 배열에서 빈 요소를 제거합니다.

답변4

전체를 셸에서 수행하고 결과를 배열에 저장하려면,

declare -A seen
for word in one two three two one
do
        if [ ! "${seen[$word]}" ]
        then
                result+=("$word")
                seen[$word]=1
        fi
done
echo "${result[@]}"

즉, 주어진 단어를 아직 보지 못했다면 해당 단어를 result배열에 추가하고 본 것으로 표시합니다. 단어가 보이면 이후에 나오는 단어를 무시하세요.

관련 정보