독특한 라인 인쇄


15

sort와 조합이 아닌 고유 한 라인을 인쇄하기위한 더 나은 솔루션이 uniq있습니까?


1
"더 나은"은 무엇을 의미합니까?
개브.

@gabe 예를 들어 전체 파일을 메모리에 저장하지 않아도됩니다.
Let_Me_Be

sort입력이 너무 커서 RAM에 맞지 않는 경우 일부 버전 (예 : GNU coreutils)은 임시 파일과 외부 병합 정렬을 사용합니다. 그리고 대부분의 다른 버전에는 -m옵션을 가지고 있으므로 입력을 청크 (예 : with split) 하여 각 청크를 정렬 한 다음 청크를 병합하여 청크를 병합 할 수 있습니다.
jhnc

답변:


25

순서대로 각 동일한 행을 하나만 인쇄하려면 :

sort -u

순서에 상관없이 고유 한 줄만 인쇄하려면

sort | uniq -u

첫 번째 발생 순서대로 각 동일한 행을 한 번만 인쇄하려면 다음을 수행하십시오.

awk '!seen[$0] {print}
     {++seen[$0]}'

고유 한 행만 첫 번째 발생 순서로 인쇄하려면 : (의 각 행을 기록하고 첫 번째 발생 인 경우 seen에도 lines입력하십시오. 한번)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
방법은 awk '!seen[$0]++ {print}'?
asoundmove

10
또는 빈 명령으로 암시 awk '!seen[$0]++'되기 때문에 더 짧습니다 {print}.
quazgar 2016 년

3

일부 (가장?) 버전 에는 해당 부분을 ​​직접 수행 sort하는 -u플래그가 uniq있습니다. 구현에 따라 일부 선 길이 제한이있을 수 있지만 이미 일반을 사용했습니다 sort|uniq.


1
어? sort -u최소한 V7로 돌아갑니다.
geekosaur

흠 ... 솔라리스 나 AIX가없는 것을 기억한다고 생각했습니다. 나는 틀렸다. 둘 다 가지고있다.
Mat

Solaris 및 AIX에는 -u512 자 라인 길이 제한이 있습니다. (실제로, 나는 솔라리스 9 선 어딘가에 5120으로
올랐다고

@geekosaur : 확실합니까? 라인 길이의 512 바이트 제한을 제거하기 위해 수행 된 작업은 Bell System Technical의 JP Linderman의 '작업 정렬 루틴 구성의 이론 및 실습'에 설명되어 있습니다. Journal, 63, 1827-1843 (1984).
Jonathan Leffler

0

펄은 당신을 위해 일합니까? 사본이 인접하지 않더라도 원래 순서대로 행을 유지할 수 있습니다. 파이썬으로 코딩하거나을 (를) 코딩 할 수도 있습니다 awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

그냥 단축 할 수 있습니다

perl -ne 'print unless $lines{$_}++;'

주어진 입력 파일 :

abc
def
abc
ghi
abc
def
abc
ghi
jkl

출력을 산출합니다 :

abc
def
ghi
jkl

$ line은 어디에서 정의됩니까?
그레그 레 벤탈

그렇지 않습니다. 이 없기 때문에 A는 use strict;use warnings;(실제로, 그것이 strict그 여기에 가장 관련), 사용에 대한 아무런 불만이 없다 %lines가 정의되기 전에는. 엄격하게 실행하는 경우 my %lines;루프 앞에 줄이 있어야합니다. 해시도 %lines; 해시의 한 요소는 $lines{$_}표기법을 사용하여 참조 됩니다.
Jonathan Leffler

sort솔루션이 대량의 데이터에 더 좋을 것이라고 생각합니다 (OP는 "전체 파일을 메모리에 저장"하는 데 관심이있었습니다). sort데이터가 사용 가능한 메모리보다 큰 경우 코어 외부 정렬을 수행합니다.
Kusalananda

0

이 질문에 대한 답변으로 @Gilles의 고유 행 인쇄에 언급 된 답변의 마지막 부분에 대해 두 개의 해시를 사용할 필요가 없도록했습니다.

이 해결 방법은 다음과 같습니다. 고유 한 행만 첫 번째 순서대로 인쇄합니다.

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

여기서 "카운터"는 이전에 처리 된 것과 유사한 각 라인의 수를 저장합니다.
마지막으로 카운터 값이 1 인 행만 인쇄합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.