[unix] 첫 번째 행을 제외하고 파일에서 추가 헤더 행을 제거하십시오.

이 장난감 예제와 같은 파일이 있습니다. 내 실제 파일에는 4 백만 줄이 있으며 그중 약 10 줄을 삭제해야합니다.

ID  Data1  Data2
1    100    100
2    100    200
3    200    100
ID  Data1  Data2
4    100    100
ID  Data1  Data2
5    200    200

첫 번째 줄을 제외하고 머리글처럼 보이는 줄을 삭제하고 싶습니다.

최종 파일 :

ID  Data1  Data2
1    100    100
2    100    200
3    200    100
4    100    100
5    200    200

어떻게해야합니까?



답변

header=$(head -n 1 input)
(printf "%s\n" "$header";
 grep -vFxe "$header" input
) > output
  1. 입력 파일의 헤더 행을 변수로 가져옵니다.
  2. 헤더를 인쇄
  3. 파일을 처리하여 grep헤더와 일치하는 줄을 생략하십시오.
  4. 위 두 단계의 출력을 출력 파일로 캡처

답변

당신이 사용할 수있는

sed '2,${/ID/d;}'

그러면 2 행부터 ID가있는 행이 삭제됩니다.


답변

중괄호를 좋아하지 않는 사람들을 위해

sed -e '1n' -e '/^ID/d'
  • npass라인 번호를 의미 합니다.1
  • d 로 시작하는 모든 일치하는 줄을 삭제하십시오. ^ID

답변

재미있는 것이 있습니다. sed직접 사용 하여 첫 번째 줄의 모든 복사본을 제거하고 다른 모든 것을 제자리에 그대로 둘 수 있습니다 (첫 번째 줄 자체 포함).

sed '1{h;n;};G;/^\(.*\)\n\1$/d;s/\n.*$//' input

1{h;n;}첫 번째 행을 보류 공간에 넣고 인쇄 한 후 다음 행을 읽고 sed첫 번째 행 의 나머지 명령을 생략합니다 . (또한 두 번째 줄에 대한 첫 번째 1테스트건너 뛰지두 번째 줄 에는 해당 테스트가 적용되지 않으므로 중요하지 않습니다.)

G 패턴 공간에 줄 바꿈 다음에 보류 공간의 내용을 추가합니다.

/^\(.*\)\n\1$/d줄 바꿈 뒤 부분 (즉, 보류 공간에서 추가 된 부분)이 줄 바꿈 앞 부분과 정확히 일치하면 패턴 공간의 내용을 삭제합니다 (따라서 다음 줄로 건너 뛰기). 헤더를 복제하는 행이 삭제되는 위치입니다.

s/\n.*$//G명령 에 의해 추가 된 텍스트 부분을 삭제하여 인쇄되는 내용이 파일에서 텍스트 행만됩니다.

그러나 정규 표현식이 비싸기 때문에 약간 더 빠른 접근 방식은 동일한 조건을 사용하고 (부정) P개행 뒤 부분 (즉, 보류 공간에서 추가 된 부분 ) 부분과 정확하게 일치 하지 않으면 개행까지 찢는 것입니다. 줄 바꿈 전에 무조건 패턴 공간을 삭제하십시오.

sed '1{h;n;};G;/^\(.*\)\n\1$/!P;d' input

입력시 출력은 다음과 같습니다.

ID  Data1  Data2
1    100    100
2    100    200
3    200    100
4    100    100
5    200    200


답변

첫 번째 줄을 미리 알 필요가없는 몇 가지 선택 사항은 다음과 같습니다.

perl -ne 'print unless $_ eq $k; $k=$_ if $.==1;

-n플래그는 perl에게 입력 파일을 반복하여 각 줄을로 저장하도록 지시 $_합니다. 은 $k=$_ if $.==1;첫 번째 줄 (저장 $.하므로, 줄 번호 $.==1로만 1 라인 true가됩니다) $k. print unless $k eq $_인쇄는 하나의 저장과 동일하지 않은 경우, 현재의 행 $k.

다른 방법으로 awk:

awk '$0!=x;(NR==1){x=$0}' file

여기에서 현재 줄이 변수에 저장된 내용과 같은지 테스트합니다 x. 테스트 $0!=x가 true로 평가되면 (현재 행 $0이와 동일하지 않은 경우 x) true 표현식에서 awk의 기본 조치가 인쇄이므로 행이 인쇄됩니다. 첫 번째 줄 ( NR==1)은로 저장됩니다 x. 현재 행과 일치하는지 확인한 후에이 작업을 수행하므로 x첫 번째 행도 인쇄됩니다.


답변

AWK는 이러한 목적을위한 매우 훌륭한 도구입니다. 샘플 코드는 다음과 같습니다.

$ awk 'NR == 1 {print} NR != 1 && $0!~/ID  Data1  Data2/' rmLines.txt | head -n 10
ID  Data1  Data2
1    100    100
     100    200
3    200    100
1    100    100
     100    200
3    200    100
1    100    100
     100    200
3    200    100

고장 :

  • NR == 1 {print} 텍스트 파일의 첫 줄을 인쇄하도록 지시합니다
  • NR != 1 && $0!~/ID Data1 Data2/ 논리 연산자 &&는 AWK에 1과 같지 않고 포함하지 않은 행을 인쇄하도록 지시합니다 ID Data1 Data2. {print}부분 의 부족에 주목하십시오 . awk에서 테스트 조건이 true로 평가되면 라인이 인쇄되는 것으로 가정됩니다.
  • | head -n 10출력을 처음 10 개 라인으로 만 제한하는 작은 추가 사항입니다. AWK부품 자체와 관련이 없으며 데모 목적으로 만 사용됩니다.

파일에서 원하는 경우 다음 > newFile.txt과 같이 명령 끝에 추가하여 명령 출력을 경로 재 지정하십시오 .

awk 'NR == 1 {print} NR != 1 && $0!~/ID  Data1  Data2/' rmLines.txt > newFile.txt

어떻게 유지합니까? 실제로는 꽤 좋습니다.

$ time awk 'NR == 1 {print} NR != 1 && $0!~/ID  Data1  Data2/' rmLines.txt > /dev/null
    0m3.60s real     0m3.53s user     0m0.06s system

사이드 노트

생성 된 샘플 파일은 백만에서 백만까지 반복하고 파일의 처음 네 줄을 인쇄하기 위해 수행되었으므로 0.09 초가 걸렸습니다.

awk 'BEGIN{ for(i=1;i<=1000000;i++) printf("ID  Data1  Data2\n1    100    100\n     100    200\n3    200    100\n");  }' > rmLines.txt


답변

Awk, 모든 헤더에 자동으로 적응 :

awk '( FNR == 1) {header=$0;print $0;}
     ( FNR > 1) && ($0 != header) { print $0;}'  file1  file2 ....

즉, 첫 번째 줄에서 헤더를 가져 와서 인쇄하면 해당 헤더에서 다음 줄 DIFFERENT가 인쇄됩니다.

FNR = 현재 파일의 레코드 수. 여러 파일을 가질 수 있으며 각 파일에서 동일하게 수행됩니다.