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.

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

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 $_;
}

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

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

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

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.


1

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

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.