Memasukkan:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Output yang diharapkan:
1
2
3
4
Jadi, saya hanya perlu memiliki nilai 1, 5, 9, 13 file dalam file output. Bagaimana cara melakukannya?
Memasukkan:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Output yang diharapkan:
1
2
3
4
Jadi, saya hanya perlu memiliki nilai 1, 5, 9, 13 file dalam file output. Bagaimana cara melakukannya?
Jawaban:
Menggunakan AWK:
awk '!((NR - 1) % 4)' input > output
Mencari tahu bagaimana ini bekerja dibiarkan sebagai latihan untuk pembaca.
NR % 4 == 1IMO akan lebih terbaca.
Menggunakan split (GNU coreutils):
split -nr/1/4 input > output
-nmenghasilkan CHUNKSfile outputdan CHUNKSsebagai
r/K/N gunakan distribusi round robin dan hanya keluaran Kth of N ke stdout tanpa memisahkan garis / catatanDengan GNU sed:
sed '1~4!d' < input > output
Dengan standar sed:
sed -n 'p;n;n;n' < input > output
Dengan 1dan 4dalam $ndan $ivariabel:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Versi python, hanya untuk bersenang-senang:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)harus dapat melakukan pekerjaan sambil mengkonsumsi lebih sedikit memori
readlines(maka menghirup seluruh file ke dalam memori), Anda dapat menggunakan f.readlines()[::4]untuk mendapatkan setiap baris keempat. Jadi bisa digunakan print(''.join(f.readlines()[::4])).
POSIX sed: metode ini menggunakan sed posixly dan dapat dijalankan di mana-mana, atau setidaknya seds yang menghormati posix.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Lainnya adalah pembuatan kode sed terprogram untuk tujuan skalabilitas:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl: kita mengisi array A sampai ukurannya 4. Kemudian kita mencetak elemen pertamanya dan juga menghapus array.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Panggil dengan scriptname filename skip(4 dalam kasus Anda) Ini berfungsi dengan menarik itergaris dari atas file dan kemudian hanya mengeluarkan yang terakhir. Itu kemudian meningkat iteroleh skipsdan mengulangi selama nilai iterbelum melebihi linesdalam 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
Bash murni:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile adalah builtin yang ditambahkan dalam Bash 4 yang membaca input standar ke dalam array, di sini dinamai lines, dengan satu baris per entri. The -tpilihan strip baris akhir.
Jika Anda ingin mencetak setiap baris keempat mulai dari baris 4, maka Anda dapat melakukannya dalam satu perintah menggunakan mapfileopsi panggilan balik -C, yang menjalankan kode yang disediakan setiap begitu banyak baris, dengan interval yang diberikan oleh -c. Indeks array saat ini dan baris berikutnya yang akan diberikan diberikan kepada kode sebagai argumen.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Ini menggunakan printfbuiltin; kode format %.0smenekan argumen pertama (indeks), jadi hanya baris yang dicetak.
Anda dapat menggunakan perintah yang sama untuk mencetak setiap baris keempat mulai dari baris 1, 2, atau 3, tetapi Anda harus menambahkan sebelumnya 3, 2, atau 1 baris inputsebelum memasukkannya mapfile, yang menurut saya lebih banyak masalah daripada nilainya .
Ini juga berfungsi:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Di sini, printfmengkonsumsi empat entri array linessekaligus, hanya mencetak yang pertama dan melewatkan tiga lainnya dengan %.0s. Saya tidak suka ini karena Anda harus mengutak-atik string format secara manual untuk interval atau titik awal yang berbeda.
sed -n '1~4p'