Ulangi setiap baris beberapa kali

17

Ingin agar setiap baris dalam file diulang beberapa kali.

mis. minta setiap baris diulang empat kali:

a
b
c

menjadi:

a
a
a
a
b
b
b
b
c
c
c
c

Saya telah melakukan beberapa pencarian, dan ada banyak pertanyaan dan jawaban di sepanjang baris melakukan kebalikan, misalnya menggabungkan garis duplikat menjadi garis tunggal, dan mungkin beberapa tentang menggandakan garis dengan mencetaknya lagi.

Akan mudah untuk melakukan ini di C, tapi saya berharap saya tahu lebih banyak tentang perintah asli sehingga saya tidak perlu menggunakan jenis-jenis lemparan-sekali saja sepanjang waktu.

Yimin Rong
sumber

Jawaban:

19
  • Perl:

    perl -ne 'for$i(0..3){print}' file

    dan saya harus menambahkan yang ini diposting sebagai komentar oleh @derobert karena itu keren:

    perl -ne 'print "$_" x4'
  • awk dan varian:

    awk '{for(i=0;i<4;i++)print}' file
  • bash

    while read line; do for i in {1..4}; do echo "$line"; done; done < file
terdon
sumber
1
awk's fortidak perlu kawat gigi jika hanya ada satu perintah untuk mengulang. Dan perllebih sederhana jika Anda menggunakan foreachlingkaran: for$i(0..3){print}.
manatwork
4
Perl Alternatif: perl -ne 'print(($_)x4)'. Juga, Anda harus mengutip $line(dalam gema) di versi bash Anda.
derobert
Dalam kasus saya, saya membutuhkan akhir baris Windows. seperti yang terlihat di sini dapat dicapai denganBEGIN { ORS="\r\n" }
The Red Pea
34

Saya ingin tahu apakah ini berubah menjadi pertandingan golf :

sed 'p;p;p' 
awk '1;1;1;1' 
perl -lpE 'say;say;say'   # if Paul McCartney and Michael Jackson were hackers...

Penjelasan:

pPerintah sed adalah untuk mencetak baris saat ini. Perilaku default adalah untuk mencetak baris saat ini sebelum pindah ke baris berikutnya (itu sebabnya -nAnda harus mematikannya). Beberapa seds yang lebih tua tidak memiliki titik koma (saya pikir) sehingga mungkin Anda harus melakukannyased -e p -e p -e p

Awk bekerja dengan condition {action}pasangan. Jika tindakan dihilangkan, standarnya adalah untuk mencetak baris saat ini jika kondisi kembali benar. Awk, seperti banyak bahasa mirip-C, memperlakukan 1sebagai benar. (Untuk kelengkapan, jika kondisi dihilangkan, tindakan akan dieksekusi untuk setiap catatan.)

Banyak fungsi perl memanfaatkan variabel "default". Lapisan satu ini setara dengan (pada perl 5.16):

$ perl -MO=Deparse -lpE 'say;say;say'
BEGIN { $/ = "\n"; $\ = "\n"; }
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    say $_;
    say $_;
    say $_;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
glenn jackman
sumber
1
+1, jika ya, Anda menang :) Apa yang sebenarnya 1dilakukan di awk? Singkatan untuk print $0?
terdon
3
Pernyataan awk terdiri dari kondisi dan blok, keduanya opsional, tetapi harus ada. Kondisi default adalah 1(benar); blok default setara dengan {print}. Jadi pernyataan 1itu berarti mencetak buffer baris saat ini ( {print}). ( {print}dan {print $0}sebagian besar sama, qed.)
Arcege
Saya belum pernah mendengar tentang sedyang tidak mendukung titik koma sebagai terminator perintah; apakah memang ada yang seperti itu?
Wildcard
4
sed -n '{p;p;p;p;}' file

awk '{print;print;print;print;}' file
Hauke ​​Laging
sumber
4

Anda dapat melakukan ini tanpa memerlukan sed, perlatau awk.

$ for i in `cat <file>` ; do seq <#> <#> | xargs -i -- echo $i ; done

atau menggunakan loop sementara:

$ while read i ; do seq <#> <#> | xargs -i -- echo $i ; done < <file>

Contohnya

untuk loop
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
sementara lingkaran
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c
slm
sumber
Saya pikir versi for loop akan terputus pada setiap baris yang berisi spasi, jadi loop sementara harus lebih disukai. Kalau tidak, +1 karena saya pengisap untuk solusi shell.
evilsoup
@ evilsoup - ya orang lain yang menyebutkan ini juga pada beberapa kode yang saya posting di Q&A lain. Saya pikir itulah keunggulan utama while over untuk, loop sementara lebih toleran terhadap pemisah $ IFS dan akan dibagi pada end-of-line sedangkan untuk split pada $ IFS.
slm
1

Menggunakan shell murni:

repeats=4
while read line; do yes $line|head --lines=$repeats; done < infile > outfile
pengguna176581
sumber
Apakah ada yang tahu cara membuat ya dianggap --helpsebagai string dan bukan opsi? [pertimbangkan kasus di mana lineada --helpatau pilihan lain]
user176581
ya,yes -- --help
don_crissti
Menggunakan yesdan headberarti ini bukan "murni shell"
glenn jackman
1

Ini mungkin bekerja untuk Anda (sed GNU):

sed 'h;:a;s/[^\n]\+/&/4;t;G;ba' file

Akan mengulangi setiap baris 4 kali.

Atau jika Anda lebih suka:

sed 'h;:a;s/\n/&/3;t;G;ba' file

Di mana Anda mengulangi setiap baris 3 kali lagi.

potong
sumber
1

@potong jawaban tidak bekerja dengan baris kosong, ganti \+dengan *harus memperbaikinya:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
Jan Kos
sumber