파이프로 구분된 파일의 각 줄이 동일한지 확인하는 방법

파이프로 구분된 파일의 각 줄이 동일한지 확인하는 방법

수백만 개의 레코드를 포함할 수 있는 파이프로 구분된 파일이 있습니다. 내가 원하는 것은 파일을 정렬하고 파일에 중복된 줄이 있으면 제거하는 것입니다.

그런 다음 처음 32개 열을 확인하여 첫 번째 행의 내용이 두 번째 행과 일치하는지 확인해야 합니다. 그렇다면 두 번째 행을 삭제하고 첫 번째 행과 세 번째 행을 다시 확인합니다(이전 행이 삭제되었으므로 이제 동일하므로 두 번째 행이 됩니다). 동일한 경우 세 번째 줄도 삭제하고 불일치가 발생할 때까지 첫 번째 줄을 파일의 다음 줄과 계속 비교합니다. 예: 입력 파일:

a|a1|a2|a3|a4|...|a32|[email protected]
a|a1|a2|a3|a4|...|a32|[email protected]$1553:2015-02-14 
a|a1|a2|a3|a4|...|a32|[email protected]:2015-03-01 
a|a1|a2|a3|a4|...|a32|[email protected]$121:2015-01-31 
a|a1|a2|a3|a4|...|a32|[email protected]$293:2015-02-28 
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]:2014:05:24 
c|c1|c2|c3|c4|...|c32|[email protected] 
c|c1|c2|c3|c4|...|c32|$200:2011:12:06 
c|c1|c2|c3|c4|...|c32|[email protected]$214:2001:01:31 

위의 예에는 33개의 필드가 있으며 "..."는 연속성을 나타내는 데 사용됩니다. 따라서 보시다시피 처음 4개 행은 동일합니다(예제에서는 "a32"로 표시되는 필드 번호 32만 비교됩니다). 따라서 첫 번째 항목만 유지하고 나머지 항목은 삭제하면 됩니다. 다시 말하지만, 로 시작하는 열에는 b5개의 동일한 레코드가 있으므로 마지막 4개를 다시 삭제하고 첫 번째 레코드를 유지합니다. 로 시작하는 레코드의 경우 c3개의 레코드만 있으므로 마지막 2개는 삭제하고 첫 번째는 유지해야 합니다. 따라서 출력 파일은 다음과 같습니다.

필수 출력 파일:

a|a1|a2|a3|a4|...|a32|[email protected]
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
c|c1|c2|c3|c4|...|c32|[email protected] 

이 작업을 수행하기 위해 일반 루프와 sed 명령을 사용하는 것을 고려하고 있지만 프로세스 속도가 크게 느려질 것입니다. 그렇다면 ack이 검색/작업을 더 빠르게 사용할 수 있는 방법이 있습니까 ?

답변1

키 1부터 32까지 정렬(-k1,32)수직 스트립구분 기호로 -t'|'.
-u의미: 동일 실행(키 조합)의 첫 번째 줄만 출력합니다. 자세한 내용은
옵션을 참조하세요 man sort.sort

sort -t'|' -k1,32 -u infile

물론 위 코드는 정렬된 출력을 생성합니다.
그러나 입력 파일에서와 같이 처음 발견된 행의 순서를 동일하게 유지하려면 다음을 사용하십시오.

nl -s'|' -ba infile | sort -t'|' -k2,5 -u | sort -t'|' -k1 -n | cut -d'|' -f2-

nl연속된 줄 번호를 접두사로 사용하세요. 이 줄 번호는 다음 cut단계를 따릅니다 sort.
두 번째 방법의 출력은 다음과 같습니다.테든펄 솔루션.

답변2

Peter의 sort방법은 거의 확실히 가장 효과적이므로 사용하는 것이 좋습니다. 다양성을 위해 Perl 솔루션은 다음과 같습니다.

perl -F"\|" -lane  'push @G,$_ unless ++$k{join("\|",@F[0..31])}>1;
                    END{print join "\n",@G}' file 

관련 정보