파일에서 특정 줄 (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

로 1와 4의 $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을 초과하지 않는 lines로 file.

#!/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.