이 장난감 예제와 같은 파일이 있습니다. 내 실제 파일에는 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
- 입력 파일의 헤더 행을 변수로 가져옵니다.
- 헤더를 인쇄
- 파일을 처리하여
grep
헤더와 일치하는 줄을 생략하십시오. - 위 두 단계의 출력을 출력 파일로 캡처
답변
당신이 사용할 수있는
sed '2,${/ID/d;}'
그러면 2 행부터 ID가있는 행이 삭제됩니다.
답변
중괄호를 좋아하지 않는 사람들을 위해
sed -e '1n' -e '/^ID/d'
n
pass
라인 번호를 의미 합니다.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 = 현재 파일의 레코드 수. 여러 파일을 가질 수 있으며 각 파일에서 동일하게 수행됩니다.