Giriş:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Beklenen çıktı:
1
2
3
4
Yani, çıktı dosyasındaki dosyanın sadece 1, 5, 9, 13. Değerlerine ihtiyacım var. Bu nasıl yapılır?
Giriş:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Beklenen çıktı:
1
2
3
4
Yani, çıktı dosyasındaki dosyanın sadece 1, 5, 9, 13. Değerlerine ihtiyacım var. Bu nasıl yapılır?
Yanıtlar:
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.
NR % 4 == 1daha okunaklı bir IMO olurdu.
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ınGNU 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)'
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
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])).
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
İ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
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.
sed -n '1~4p'