파일의 모든 n 번째 줄만 유지하는 방법


71

상당히 큰 CSV 파일 (75MB)이 있습니다. 그래프를 만들려고하므로 모든 데이터가 필요하지 않습니다.

Rewording : n 줄을 삭제 한 다음 한 줄을 유지 한 다음 n 줄을 삭제하고 싶습니다.

따라서 파일이 다음과 같은 경우

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6

n = 2이면 출력은 다음과 같습니다.

Line 3
Line 6

sed작업을 수행 할 수있을 것 같지만 방법을 알 수 없었습니다. bash 명령이 이상적이지만 모든 솔루션을 사용할 수 있습니다.


2
1, 4, 7 등이 아닌 1, 3, 6 등을 실제로 원하십니까?
Ilmari Karonen

2
CSV 파일이기 때문에 첫 번째 줄에는 메타 데이터 (예 : 필드 이름)가 포함되어 있다고 가정합니다. 그렇다면 질문은 "처음부터 n 번째 줄"이어야합니다.
iglvzx 2014 년

7
1, 3, 6은 여전히 ​​이해가되지 않습니다!
wim

1
n = 2가 삼각형 숫자 (1, 3, 6, 10, 15, 21 등)의 마법 값이 아니면 1, 3, 5 여야합니다.
rjmunro

4
요청한 내용 ( "n 번째 줄", "n = 2")과 원하는 출력 (줄 3, 줄 6)을 일치 시키도록 질문을 업데이트 할 수 있습니까? 미래의 독자들은 혼란 스러울 것입니다.
Keith Thompson

답변:


121
~ $ awk 'NR == 1 || NR % 3 == 0' yourfile
Line 1
Line 3
Line 6

NR(레코드 수) 변수는 기본 행 수가 RS(레코드 세퍼레이터)의 새 행이므로 레코드 행 수입니다 . 패턴 및 작업은 awk의 기본 형식에서 선택 사항입니다 'pattern {actions}'. 패턴 부분 만 제공하면 패턴 조건에 대한 awk모든 필드 $0를 씁니다 true.


8
기본값 덕분에 그다지 필요하지 않습니다.awk 'NR == 1 || NR % 3 == 0'
Kevin

@selman : Kevin의 솔루션이 마음에 들면 답변을 업데이트하는 것이 좋습니다.
Keith Thompson

4
왜 그런지 설명해 주시겠습니까? 그렇게하면 누군가가 약간 조정하고 싶다면, 여러분의 설명이 도움이 되길 바랍니다.
Ivo Flipse

나는이 접근법이 나에게 라인 1과 2를 건드리지 않는 것을 발견했다. awk 'NR == 1 || NR % 2 == 0' myfile.txt | wc -l원본 파일의 행 수가 짝수 인 동안 홀수 로 확인됩니다 . @kev 답변은 내 테스트 사례에서 가장 잘 작동합니다.
Daniel Da Cunha

58

sed 또한 이것을 할 수 있습니다 :

$ sed -n '1p;0~3p' input.txt
Line 1
Line 3
Line 6

man sed다음 ~과 같이 설명 합니다 :

first ~ step 첫 번째 줄부터 시작하여 모든 단계의 줄을 일치시킵니다. 예를 들어``sed -n 1 ~ 2p ''는 입력 스트림의 모든 홀수 라인을 인쇄하고 주소 2 ~ 5는 두 번째 라인부터 다섯 번째 라인마다 일치합니다. 첫 번째는 0이 될 수 있습니다. 이 경우 sed는 마치 단계와 동일한 것처럼 작동합니다. (이것은 확장입니다.)


6
이 명령을 설명해 주시겠습니까?
qed

1
@qed 설명 : 1p첫 번째 행을 0~3p인쇄하고 3 번째 줄부터 시작하여 세 번째 줄 1p을 모두 인쇄합니다 ( 따라서 1 행을 인쇄해야합니다). 그러나 이것은 0~3표준이 아니라 GNU sed 확장입니다.
Arkku

"이것은 확장입니다." 어떤 버전을 사용하고 있습니까?
Victor

이 답변은 Windows PowerShell에 많은 도움이되었습니다. sed -n '1p;0~10p' '.\in.txt' > out.txt축소 된 파일을 출력 파일로 인쇄하려면 다음과 같이 확장했습니다 .
kimliv 2016 년

22

도 이것을 할 수 있습니다 :

while (<>) {
    print  if $. % 3 == 1;
}

이 프로그램은 입력의 첫 번째 줄과 그 후 세 번째 줄을 인쇄합니다.

이것을 조금 설명하기 위해 <>, 라인 입력 연산자 while는 이런 루프 에서 사용될 때 입력 라인을 반복 합니다. 특수 변수 $.에는 지금까지 읽은 줄 수가 포함되어 %있으며 계수 연산자입니다.

이 코드는 -n-e스위치를 사용하여 하나의 라이너로 더 간결하게 작성할 수 있습니다 .

perl -ne 'print if $. % 3 == 1'  < input.txt  > output.txt

-e그동안 스위치, 커맨드 라인 파라미터로 실행 펄 코드의 조각을 얻어 -n스위치 암시에 코드를 감싸는 while위와 같은 루프.


편집 : 내가 먼저 당신이 원하는 가정으로 사실 ... 오히려 라인 1, 4, 7, 10,보다, 예에서와 같이 선 1, 3, 6, 9, ...을 얻으려면, 교체 $. % 3 == 1와 함께 $. == 1 or $. % 3 == 0.


7

당신이 함께하고 싶어 배쉬 시도 할 수있는 스크립트

#!/bin/sh

echo Please enter the file name
read fname
echo Please enter the Nth lines that you want to keep
read n

exec<$fname
value=0
while read line
do
    if [ $(( $value % $n )) -eq 0 ] ; then
        echo -e "$line" >> new_file.txt
    fi
        let value=value+1 
done
echo "Check the 'new_file.txt' that has been created in this directory";

"read_lines.sh"로 저장하고 bash 파일에 + x 권한을 부여해야합니다.

chmod +x ./read_lines.sh

1
이것을 표준 출력으로 내 보내면 인수에서 건너 뛸 줄을 읽지 않고 표준에서 파일을 읽으면 더 간단하고 유용합니다. 여전히을 수행하여 new_file.txt를 만들 수 있습니다 ./read_lines.sh > new_file.txt.
rjmunro

4

프로세스를 생성하지 않는 순수한 bash의 솔루션은 다음과 같습니다.

{ for f in {1..2}; do read line; done;
  while read line; do
    echo $line;
    for f in {1..2}; do read line; done;
  done; } < file

첫 줄은 파일 시작 부분에서 2 줄을 while건너 뛰고 다음 줄을 인쇄하고 2 줄을 다시 건너 뜁니다.

파일이 작 으면 프로세스를 시작하지 않기 때문에 작업을 수행하는 매우 효율적인 방법입니다. 파일이 크면 sedio보다 처리하는 것이 더 효율적이므로 사용해야합니다 bash.


1

Python 버전 (Python 2와 Python 3 모두) :

python2 -c "print(''.join(open('file.txt').readlines()[::3]))"

[::3]더 많은 제어를 위해 시작, 종료 및 단계 크기 매개 변수로 대체하십시오 . 예를 들어 [10:36:5]10,15, ..., 35 줄을 표시합니다.

readlines()줄 끝을 유지하기 때문에 , 원래 마지막 줄이 선택된 단계 크기에 의해 나오지 않는 한,이 호출의 출력은 빈 마지막 줄로 끝날 수 있습니다.

스트림 버전도 가능합니다 (여기서 스트림이 완료된 후에 만 ​​출력 됨).

python -c "import sys;print(''.join(list(sys.stdin)[::3]))" < file.txt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.