이 문서를 보면(주석은 문서의 일부가 아니라 설명의 일부입니다)...
x,a,001,b,c,d,y
x,a,002,b,c,e,yy
x,bb,003,b,d,e,y
x,c,004,b,d,e,y
x,c,005,b,d,e,y # nb - dupe of row 4
x,dd,006,b,d,e,y
x,c,007,b,d,e,y # nb - dupe of row 4 and 5
x,dd,008,b,d,f,y
x,dd,009,b,d,e,y # nb - dupe of row 6
x,e,010,b,d,f,y
...다음과 같은 출력을 얻고 싶습니다.
x,a,001,b,c,d,y
x,a,002,b,c,e,yy
x,bb,003,b,d,e,y
x,c,004,b,d,e,y
x,dd,006,b,d,e,y
x,dd,008,b,d,f,y
x,e,010,b,d,f,y
파일에서 세 번째 열을 제거한 다음 파일에서 uniq를 실행하고 나머지 행의 세 번째 열 값이 올바른 위치에 다시 추가되면 위의 결과를 얻습니다.
하지만 저는 정말로 그런 일을 할 수 있는 뭔가를 생각해내려고 노력하고 있어요. 저는 Linux의 텍스트 처리 유틸리티에 대해 배울 수 있는 기회를 환영했습니다.
성능: 파일이 1MB를 넘기는 것은 불가능해 보이고 하루에 1개의 파일만 생성됩니다.
대상: Debian GNU/Linux 7 amd64, 256MB/Xeon.
편집: 필드가 고정 너비가 아니기 때문에 예제를 적용하면 uniq --skip-chars=n
관련된 솔루션이 내가 아는 한 작동하지 않습니다.
답변1
이를 통해 awk
다음을 수행할 수 있습니다.
awk -F, -vOFS=, '{l=$0; $3=""}; ! ($0 in seen) {print l; seen[$0]}'
답변2
가장 간단한 방법:
sort -u -t, -k1,2 -k4
-u
: 다음과 같은 첫 번째 라인만 출력합니다.-t,
: 필드 구분자로 쉼표를 사용합니다.-k1,2 -k4
: 1,2,4번 필드와 나머지 필드만 정렬
또 다른 옵션은 데이터를 양쪽에서 재배열하는 것입니다 sed
(GNU 옵션 참고 -r
). 이렇게 하려면 레코드가 대부분 고정 길이여야 합니다. 그렇지 않으면 실패할 것입니다(거의 눈에 띄지 않습니다).
sed -r 's/^([^,]+,[^,]+)(,[^,]+)(.*)$/\1\3\2/' \
| sort \
| uniq -w 12 \
| sed -r 's/^([^,]+,[^,]+)(.*)(,[^,]+)$/\1\3\2/'
필요한 경우 sort
숫자로 정렬하기 위해 끝에 다른 항목을 추가 할 수 있습니다(해당 -k
옵션을 사용하여 수행해야 하는 정렬을 기준으로 선택 - 예: sed -k3 -t,
) .
예를 들어 Perl에서는 고유성을 확인하려는 부분을 해시(전체 행의 값)의 키로 사용하고 키가 아직 정의되지 않은 경우에만 해시를 삽입할 수 있습니다. 이것은 확실히 sed
(or awk
) 를 사용하는 것보다 더 유연할 뿐만 아니라 더 많은 쓰기 기능을 제공합니다(저는 Perl 전문가와는 거리가 멀기 때문에 더 우아한 방식으로 수행할 수 있습니다. Perl과 유사한 Perl 솔루션에 대한 다른 답변을 참조하세요).
#!/usr/bin/perl
use strict;
my %lines;
while (<>) {
(my $k1, my $v, my $k2) = /^([^,]+,[^,]+,)([^,]+)(,.*)$/;
my $k = $k1 . $k2;
if (!exists($lines{$k})) {
$lines{$k} = $_;
}
}
for my $k (sort(keys(%lines))) {
print $lines{$k};
}
답변3
이를 수행하는 한 가지 방법은 다음과 같습니다 awk | sort | uniq | awk
.
awk -F, '{a=$1;$1=$3;$3=a;print}' file | sort -k 2 | uniq -f 1 | awk -v OFS=',' '{a=$1;$1=$3;$3=a;print}'
답변4
더 간단한 Perl 접근 방식은 다음과 같습니다.
perl -F"," -ane '$a=join(",",@F[0,1,3 .. $#F]); print unless $k{$a}; $k{$a}++' file
-a
필드를 @F
배열 로 분할 하고 -F","
필드 구분 기호를 로 설정합니다 ,
. 입력 파일의 각 행에서 -n
지정된 스크립트를 실행함을 나타냅니다.-e
아이디어는 배열 슬라이스(배열 끝까지 요소 0,1 및 3)를 가져와 문자열( $a
)로 연결하고 해당 문자열을 해시(연관 배열) 참조로 사용하는 것입니다. 그런 다음 해시 키가 이전에 표시되지 않은 경우에만 각 줄이 인쇄됩니다.