정렬된 고유 목록을 가져와야 하는 사람을 볼 때마다 그들은 항상 이를 sort | uniq
. 나는 그것이 사용되는 예를 본 적이 없습니다 sort -u
. 왜 안 돼? 차이점은 무엇이며 정렬 시 고유 플래그보다 uniq를 사용하는 것이 더 나은 이유는 무엇입니까?
답변1
sort | uniq
이전에도 있었고 sort -u
더 넓은 범위의 시스템과 호환되지만 거의 모든 최신 시스템이 이를 지원합니다. -u
바로 POSIX입니다. 이것은 대부분 존재하지 않았던 시절에 대한 후퇴입니다 (사람들은 알려진 방식이 계속 작동하는 것으로 알려진 경우 자신의 방법을 바꾸려는 경향이 없을 것입니다. 입양과 비교해 sort -u
보세요 ).ifconfig
ip
파일에서 중복 항목을 제거하려면 정렬(적어도 표준 사례에서는)이 필요하고 정렬을 위한 매우 일반적인 사용 사례이므로 둘은 병합될 가능성이 높습니다. 두 작업을 동시에 수행할 수 있는 능력으로 인해(그리고 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
답변2
POSIX 호환 sort
s 및 uniq
s의 경우(GNU는 uniq
현재 이와 관련하여 호환되지 않습니다)차이가 있습니다sort
로케일의 데이터 정렬 알고리즘을 사용하여 문자열(일반적으로 strcoll()
문자열을 비교하는 데 사용됨)을 비교하는 동시에 바이트 uniq
값 식별자(일반적으로 사용됨 strcmp()
)를 확인합니다.
이는 적어도 두 가지 이유로 중요합니다.
일부 로케일, 특히 GNU 시스템에는 동일한 정렬을 수행하는 다양한 문자가 있습니다. 예를 들어, GNU 시스템의 en_US.UTF-8 로케일에서는 정렬 순서가 정의되어 있지 않기 때문에 모든 ① ② ③ ④ ⑤ ⑥ ⑧ ⑩... 문자²가 다른 많은 문자와 동일하게 정렬됩니다. 0123456789 아라비아 숫자의 순서는 다음과 같습니다.동부 아랍어 인도어상대방 (٠١٢٣٤٥٦٧٨٩).
의 경우
sort -u
①은 ②와 같고, 0123은 ٠١٢٣과 같으므로sort -u
하나만 유지되고, (uniq
GNU를 사용하지 않음(제외))의 경우 ①은 ②와 다르고, 0123은 ٠١٢٣과 다르므로 4개 모두 유지됩니다. 고유한 항목이 고려됩니다.uniq
strcoll()
-f
uniq
strcoll
strcmp()
바이트 간 비교만 수행하므로 문자에 관계없이 유효한 문자의 문자열(입력에 유효한 문자를 형성하지 않는 바이트 시퀀스가 있는 경우 POSIX에 따라 정의되지 않은 동작)만 비교할 수 있습니다 . 따라서sort -u
해당 줄 중 일부가 유효한 텍스트를 형성하지 않는 경우 이는 모든 고유한 줄을 제공하지 못할 수 있는 또 다른 이유입니다.sort|uniq
, 텍스트가 아닌 입력에는 아직 지정되지 않았지만 실제로는 결과적으로 고유한 줄을 제공할 가능성이 더 높습니다.
이러한 미묘함과는 별도로, 지금까지 주목되지 않은 한 가지는 uniq
전체 행이 어휘적으로 비교되는 반면 sort
s -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
1 POSIX 사양의 초기 버전은 LC_COLLATE
변수를 영향을 받는 변수로 나열하여 혼란을 일으켰습니다 uniq
. 이는 2018 버전에서 제거되었으며 위 논의에 따라 동작이 명확해졌습니다. 바라보다해당 오스틴 그룹 오류
²2019년 편집. 이러한 문제는 해결되었지만GNU libc 버전 2.30부터 유니코드 코드 포인트의 95% 이상이 여전히 정의되지 않은 순서를 가지고 있습니다.. 당신은 테스트할 수 있습니다
답변3
한 가지 차이점은 uniq
비교를 위해 필드를 건너뛰고 값의 반복 횟수를 계산하는 등 유용한 추가 옵션이 많다는 것입니다. sort
플래그 -u
는 수정되지 않은 명령의 기능만 구현합니다 uniq
.
답변4
오늘 제가 발견한 또 다른 차이점은 구분 기호를 기준으로 정렬할 때 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