문자열 "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
배열에 추가하고 본 것으로 표시합니다. 단어가 보이면 이후에 나오는 단어를 무시하세요.