"sort -u"와 "sort | 유니크”?


119

어디에서나 정렬 된 고유 목록을 가져와야하는 사람을 항상 볼 수 sort | uniq있습니다. 누군가가 sort -u대신 사용하는 예를 본 적이 없습니다 . 왜 안돼? 차이점은 무엇이며, 고유 플래그보다 uniq를 사용하여 정렬하는 것이 더 좋은 이유는 무엇입니까?


답변:


119

sort | uniqsort -u거의 모든 최신 시스템이 지원하지만 -uPOSIX 는 이전 에 존재 했으며 광범위한 시스템과 호환됩니다 . 그것은 sort -u존재하지 않았던 시대로의 대부분의 후퇴입니다 (그리고 사람들은 그들이 알고있는 방식이 계속 작동한다면 방법을 바꾸지 않는 경향이 있습니다. 단지 ifconfigip채택을보십시오).

파일 내에서 중복을 제거하려면 (적어도 표준 경우) 정렬이 필요하고 매우 일반적인 정렬 사용 사례이기 때문에 둘이 병합되었을 가능성이 있습니다. 그것은 (그리고 그것으로 인해간에 IPC를 필요로하지 않는다는 사실에 동시에 두 가지 작업을 할 수있는 결과로 빠른 내부적으로도 uniq하고 sort). 특히 파일이 큰 경우 sort -u중간 파일을 사용하여 데이터를 정렬 할 가능성이 적습니다.

내 시스템에서 나는 지속적으로 다음과 같은 결과를 얻습니다.

$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null

real        0m0.500s
user        0m0.767s
sys         0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null

real        0m0.772s
user        0m1.137s
sys         0m0.273s

또한의 반환 코드 마스크하지 않습니다 sort중요하다, (현대 껍질이이 얻을 수있는 방법, 예를 들어,이다 bash$PIPESTATUS배열은, 그러나 이것은 항상 사실이 아니었다).


31
나는 sort | uniq10에서 9 번이기 때문에 실제로 사용하는 경향이 있습니다 uniq -c.
Plutor

5
sort -u1979 년 7 월 7 일 UNIX의 일부였습니다. sort지원하지 않는 버전 -u은 실제로 고풍 적이 거나 POSIX의 표준 이전에 사실상의 표준에주의를 기울이지 않고 작성되었습니다. 2010 년부터 리눅스 쉘 에서 스택 오버 플로우 정렬 및 유니크를 참조하십시오 .
Jonathan Leffler

3
로 인해 +1 ip. 2016 년이자 2013 년이 게시물이지만 ip지금 은 명령에 대해서만 알고 있습니다.
dieend

4
"9 시간 초과 10 동안 +1 실제로 배관 중입니다 uniq -c"(및 배관을 한 번 더 배관 sort -nr | head) sort | uniqVim이 :sort u명령을 가지고 있음을 알았을 때 Vim 과 동등한 것이 궁금합니다 . 그리고 TIL도 sort -u존재합니다.
Zhuoyun Wei

사용할 때 차이가 있습니다 sort -n | uniq대를 sort -n -u. 예를 들어, 후행 및 선행 공백은 sort -n -u이전에 의해 복제 되지 않은 것으로 간주됩니다 ! echo -e 'test \n test' | sort -n -u를 반환 test하지만 echo -e 'test \n test' | sort -n | uniq두 줄을 모두 반환합니다.
mxmlnkn

46

한 가지 차이점은 uniq비교를 위해 필드를 건너 뛰고 값의 반복 횟수를 계산하는 등 유용한 추가 옵션이 많이 있다는 것입니다. sort-u플래그는 unadorned uniq명령 의 기능 만 구현합니다 .


3
유용한 답은 +0.49이지만 " 비교를 위해 필드를 건너 뛰거나 반복 횟수를 계산하는 등 후자의 유용한 옵션을 사용 sort -u하도록 출력을 전달할 수 없습니다. "와 같은 문구로 표현합니다 uniq.
l0b0

15
"정렬에서 직접 할 수있는 방법이 없다" 질문에 대답하기 때문에
naysayers

42

POSIX 호환 가진 sortS 및 uniqS (GNU는 uniq현재 그 관련하여하지 호환) 차이가있어 그에서 sort(전형적으로 사용 문자열을 비교 로케일 조합 알고리즘을 사용 strcoll()하는 동안 스트링 비교) uniq바이트 값 ID의 검사 (통상 사용 strcmp()) .

적어도 두 가지 이유로 중요합니다.

  • 일부 로케일, 특히 GNU 시스템에서는 동일하게 정렬되는 다른 문자가 있습니다. 예를 들어, GNU 시스템의 en_US.UTF-8 로켈에서 모든 ①②③④⑤⑥⑦⑧⑨⑩ ... 문자와 다른 많은 문자는 정렬 순서가 정의되지 않았으므로 동일하게 정렬됩니다. 0123456789 아라비아 숫자는 동 아랍어 인도어 문자 (٠١٢٣٤٥٦٧٨٩) 와 동일하게 정렬 됩니다.

    의 경우 sort -u①은 ② 및 0123과 ٠١٢٣와 동일하게 정렬되므로 sort -u각각 하나만 유지하지만 ((와 함께 제외 ) 를 사용하는 uniqGNU uniqstrcoll()제외 -i) ①은 ②와 다르고 0123은 ٠١٢٣과 다르므로 uniq모두 고려하십시오 4 개의 독특합니다.

  • strcoll유효한 문자의 문자열 만 비교할 수 있으며 (입력에 유효한 문자를 형성하지 않는 일련의 바이트가있는 경우 동작은 POSIX에 따라 정의되지 않음) strcmp()바이트 간 비교 만 수행하므로 문자는 신경 쓰지 않습니다. 따라서 sort -u일부는 유효한 텍스트를 형성하지 않으면 모든 고유 한 줄을 줄 수없는 또 다른 이유 입니다. sort|uniq텍스트가 아닌 입력에 대해서는 여전히 지정되어 있지 않지만 실제로는 이러한 이유로 고유 한 행을 제공 할 가능성이 높습니다.

그 미묘한 옆에, 지금까지 언급되지 않은 한 가지 즉 uniq동안, 어휘 전체 라인을 비교 sort의이 -u명령 행에서 주어진 종류의 사양을 기반으로 비교합니다.

$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c

$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00

$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0

9

대소 문자가 혼합 된 중복을 제거하기 위해 (중복 제거) 옵션 sort | uniq을 사용하려고 할 때 -u결과를 이해하기가 쉽지 않기 때문에 사용하는 것을 선호합니다 .

참고 : 아래 예제를 실행하기 전에 다음을 수행하여 표준 C 조합 순서를 시뮬레이션해야합니다.

LC_ALL=C
export LC_ALL

예를 들어, 파일을 정렬하고 중복을 제거하려면 동시에 다른 문자열의 경우를 구별하십시오.

$ cat short      #file to sort
Pear
Pear
apple
pear
Apple

$ sort short     #normal sort (in normal C collating sequence)
Apple            #the lower case words are at the end
Pear
Pear
apple
pear

$ sort -f short  #correctly sorts ignoring the C collating order
Apple            #but duplicates are still there
apple
Pear
Pear
pear

$ sort -fu short #By adding the -u option to remove duplicates it is 
apple            #difficult to ascertain the logic that sort uses to remove
Pear             #duplicates(i.e., why did it remove pear instead of Pear?)

-u중복을 제거 하는 옵션을 사용하지 않으면이 혼동이 해결됩니다 . 사용 uniq이 더 예측 가능합니다. 아래는 먼저 사례를 정렬하고 무시한 다음 전달 uniq하여 복제본을 제거합니다.

$ sort -f short | uniq
Apple
apple
Pear
pear

2
-u옵션은 첫 번째 동일 실행 을 sort출력합니다 (설명서 페이지 참조). 따라서 대소 문자를 구분하지 않는 모든 고유 행의 첫 번째 항목을 선택합니다. 중복을 제거 하는 데 사용 되는 논리 는 예측 가능합니다. sort -fusort
pallxk

3

내가 오늘 발견 한 또 다른 차이점은 정렬 sort -u하는 열을 기준으로 고유 한 플래그를 적용 하는 델리 미터를 기준으로 정렬 할 때 입니다.

$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1

$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1

$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1

이것은 Stéphane Chazelas의 답변에 언급되어 있지만 나는 당신의 모범이 너무 좋아 +1
roaima

@roaima를 지적 해 주셔서 감사합니다. 그 대답에서 그다지 명확하지 않았습니다.
Stefanos Chrs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.