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 == 1
daha okunaklı bir IMO olurdu.
split
(GNU coreutils) kullanarak :
split -nr/1/4 input > output
-n
oluşturmak CHUNKS
çıktı dosyalarınıve CHUNKS
gibi
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 1
ve 4
içeri $n
ve $i
değ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) iter
Dosyanın üstünden çizgiler çekerek ve ardından yalnızca sonuncuyu çıktılayarak çalışır. O zaman artışlarla iter
tarafından skips
değerinin sürece ve tekrarlar iter
aştı henüz lines
iç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 lines
ve her girişte bir satır bulunan bir yerleşiktir . -t
Seç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 printf
yerleşik'i kullanır ; biçim kodu %.0s
ilk 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 input
beslemeden ö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 printf
dizinin 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'