파일에서 특정 줄 (n, n + 4, n + 8, n + 12…)을 선택하는 방법은 무엇입니까?


답변:


28

AWK 사용 :

awk '!((NR - 1) % 4)' input > output

이것이 어떻게 작동하는지 알아내는 것은 독자의 연습으로 남겨 둡니다.


이 짧은 awk 과정에 감사드립니다!
darxmurf

20
NR % 4 == 1더 읽기 쉬운 IMO가 될 것입니다.
Stéphane Chazelas

12
@ Stéphane에 동의 함; 이것은 아마도 내 질문에 의문의 여지가 있지만, 잠재적으로 숙제에 대한 질문으로 나는 대답을 약간 난독 화하려고 노력한다.
Stephen Kitt

@StephenKitt 당신의 대답을 난독 화? 정말? 이것은 그렇게 할 곳이 아닙니다.
데이터

22

사용 split (GNU의로 coreutils) :

split -nr/1/4 input > output
  • -nCHUNKS출력 파일 생성

CHUNKS같은

  • r/K/N 라인 / 레코드를 분할하지 않고 라운드 로빈 분배를 사용하고 출력 Kth of N 만 stdout

1
마음을 날려. 이 답변이 내가이 SE를 좋아하는 이유입니다. 감사!
user1717828

21

GNU로 sed:

sed '1~4!d' < input > output

표준으로 sed:

sed -n 'p;n;n;n' < input > output

14$n$i변수 :

sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'

7

필수 펄 솔루션 추가 :

perl -ne 'print if $. % 4 == 1' input > output

4

재미를위한 파이썬 버전 :

with open('input.txt') as f:
    for i, line in enumerate(f.readlines()):
        if i%4 == 0:
            print(line.strip())

enumerate(f)적은 메모리를 사용하면서 작업을 수행 할 수 있어야합니다
iruvar

@iruvar 너무 깔끔합니다! 전에는 결코 깨닫지 못했습니다. 앞으로 사용할 것입니다. 이 답변으로 자유롭게 편집하십시오. 난 정말 다른 배쉬 답변 (특히 이후 최적화로 유지하지 않을거야 이 사람이 ) 확실히 갈 수있는 방법입니다.
user1717828

당신이 readlines(따라서 전체 파일을 메모리로 슬러 핑) 사용하려고한다면 , f.readlines()[::4]네 번째 줄마다 사용할 수 있습니다 . 사용할 수 있습니다 print(''.join(f.readlines()[::4])).
Nick Matteo

3

POSIX sed:이 방법은 posixly sed를 사용하므로 모든 곳에서 실행하거나 posix를 존중하는 sed를 거의 사용할 수 있습니다.

 $ sed -ne '
   /\n/!{
    H;s/.*//;x
   }

   :loop
       $bdone
       N;s/\n/&/4
       tdone
   bloop

   :done
   s/.//;P
 ' input.file

다른 하나는 확장 성 목적을위한 프로그래밍 방식의 sed 코드 생성입니다.

$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file

Perl: 크기가 4가 될 때까지 배열 A를 채 웁니다. 그런 다음 첫 번째 요소를 인쇄하고 배열을 지 웁니다.

$ perl -pe '
   $A[@A] = @A ? <> : $_ while @A < 4;
   $_ = (splice @A)[0];
' input.file

1

로 전화하십시오 scriptname filename skip(귀하의 경우 4) iter파일의 상단에서 줄을 가져 와서 마지막으로 만 출력하여 작동합니다. 다음 단위 iter별로 skips의 값으로만큼 반복된다 iter을 초과하지 않는 linesfile.

#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
 head "$file" -n $iter | tail -n 1
 iter=$(( $iter + $skips ))
done

1

순수한 배쉬 :

mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done

mapfile 은 Bash 4에 추가 된 기본 제공 lines항목으로, 항목 당 한 줄로 표준 입력을 여기에 명명 된 배열로 읽습니다 . 이 -t옵션은 최종 개행을 제거합니다.

네 번째 줄부터 네 번째 줄을 모두 인쇄하려면 mapfile의 콜백 옵션을 사용하여 하나의 명령으로 인쇄 할 수 있습니다.이 옵션 -C은 간격이 지정된 여러 줄마다 제공된 코드를 실행합니다 -c. 현재 배열 인덱스와 다음에 할당 될 행이 코드에 인수로 제공됩니다.

mapfile -t -c4 -C 'printf "%.0s%s\n"' < input

이것은 printf내장을 사용합니다 . 형식 코드 %.0s는 첫 번째 인수 (인덱스)를 억제하므로 행만 인쇄됩니다.

동일한 명령을 사용하여 줄 1, 2 또는 3에서 시작하여 모든 네 번째 줄을 인쇄 할 수는 있지만 input공급 하기 전에 3, 2 또는 1 줄을 앞에 mapfile추가해야합니다. .

이것은 또한 작동합니다 :

mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"

여기서는 한 번에 printf네 개의 항목을 소비 lines하며 첫 번째 항목 만 인쇄하고 다른 세 항목은으로 건너 뜁니다 %.0s. 다른 간격이나 시작 지점에 대해 형식 문자열로 수동으로 바이올린을 조정해야하기 때문에 이것을 좋아하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.