Dosyadan belirli satırlar (n, n + 4, n + 8, n + 12…) nasıl seçilir?


Yanıtlar:


28

AWK kullanma:

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

Bunun nasıl çalıştığını anlamak okuyucu için bir egzersiz olarak bırakılır.


Bu kısa awk kursu için teşekkürler!
darxmurf

20
NR % 4 == 1daha okunaklı bir IMO olurdu.
Stéphane Chazelas

12
Katkıda bulunan Stéphane; bu muhtemelen benim tarafımdan sorgulanabilir, ancak potansiyel olarak ödev soruları için cevaplarımı biraz
Stephen Kitt

@StephenKitt cevaplarınızı gizliyor mu? Gerçekten mi? Burası bunu yapacak yer değil.
veri

22

split (GNU coreutils) kullanarak :

split -nr/1/4 input > output
  • -noluşturmak CHUNKSçıktı dosyalarını

ve CHUNKSgibi

  • r/K/N yuvarlak robin dağılımı kullanın ve satırları / kayıtları bölmeden stdout'a yalnızca N'nin Kth çıkışını kullanın

1
Zihin karmaşası. Bunun gibi cevaplar bu SE'yi neden seviyorum. Teşekkürler!
user1717828

21

GNU ile sed:

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

Standart sed:

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

İçeri 1ve 4içeri $nve $ideğişkenler:

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

7

Zorunlu perl çözümünün eklenmesi:

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

4

Python sürümü, sadece eğlence için:

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

enumerate(f)daha az bellek tüketirken işi yapabilmelidir
iruvar

@iruvar Çok temiz! Bunu daha önce hiç farketmemiştim; gelecekte kullanacağız. Bunu bu cevaba dönüştürmekten çekinmeyin; Diğer Bash cevapları (özellikle bu ) kesinlikle gitmek için yol olduğundan gerçekten optimizasyon ile korumak değil .
user1717828

Kullanacaksanız readlines(bu nedenle tüm dosyayı belleğe kaydırırsanız), f.readlines()[::4]her dördüncü satırı almak için kullanabilirsiniz . Böylece kullanabilirsiniz print(''.join(f.readlines()[::4])).
Nick Matteo

3

POSIX sed: Bu yöntem posixly sed kullanır ve bu nedenle her yerde çalıştırılabilir veya en azından posix'e saygı duyan seds.

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

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

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

Diğeri, ölçeklenebilirlik amacıyla programlı bir sed kodu oluşturmadır:

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

Perl: boyut 4 olana kadar A dizisini doldururuz. Sonra ilk öğesini yazdırır ve diziyi temizleriz.

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

1

İle çağırın scriptname filename skip( davanızda 4) iterDosyanın üstünden çizgiler çekerek ve ardından yalnızca sonuncuyu çıktılayarak çalışır. O zaman artışlarla itertarafından skipsdeğerinin sürece ve tekrarlar iteraştı henüz linesiçinde 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

Saf Bash:

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

mapfile , Bash 4'e eklenen ve burada adlandırılmış bir diziye standart girişi okuyan linesve her girişte bir satır bulunan bir yerleşiktir . -tSeçenek nihai yeni satırlar soyarak.

4. satırdan başlayarak her dördüncü satırı yazdırmak istiyorsanız, bunu verilen komutla verilen aralıkla verilen kodu her satırda çalıştıran mapfile's geri arama seçeneğini kullanarak tek bir komutta yapabilirsiniz . Geçerli dizi dizini ve atanacak sonraki satır koda bağımsız değişken olarak verilir.-C-c

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

Bu printfyerleşik'i kullanır ; biçim kodu %.0silk bağımsız değişkeni (dizin) bastırır, böylece yalnızca satır yazdırılır.

Aynı komutu, 1, 2 veya 3 satırından başlayarak her dördüncü satırı yazdırmak için kullanabilirsiniz, ancak inputbeslemeden önce 3, 2 veya 1 satırı başa eklemeniz gerekir mapfile, ki bu da değerinden daha fazla sorun olduğunu düşünüyorum .

Bu ayrıca işe yarar:

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

Burada, bir kerede printfdizinin dört girişini tüketir lines, sadece ilkini basar ve diğer üçünü atlar %.0s. Farklı aralıklar veya başlangıç ​​noktaları için biçim dizesiyle manuel olarak uğraşmanız gerektiğinden bunu sevmiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.