Repite cada línea varias veces


17

Me gustaría tener cada línea en un archivo repetido un número fijo de veces.

Por ejemplo, que cada línea se repita cuatro veces:

a
b
c

se convierte en:

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

He realizado algunas búsquedas, y hay muchas preguntas y respuestas en el sentido de hacer lo contrario, por ejemplo, fusionar líneas duplicadas en líneas individuales, y tal vez algunas sobre duplicar líneas imprimiéndolas nuevamente.

Sería fácil hacer esto en C, pero desearía saber más sobre los comandos nativos para no tener que recurrir a este tipo de descartes todo el tiempo.

Respuestas:


19
  • Perl:

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

    y tengo que agregar este publicado como comentario por @derobert porque es genial:

    perl -ne 'print "$_" x4'
  • awk y variantes:

    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 forno necesita apoyos si sólo hay un comando para repetir. Y perles más sencillo si se utiliza foreachen bucle: for$i(0..3){print}.
manatwork

44
Perl alternativa: perl -ne 'print(($_)x4)'. Además, debe citar $line(en eco) en su versión bash.
derobert

En mi caso, necesitaba finales de línea de Windows. como se ve aquí puede lograr conBEGIN { ORS="\r\n" }
The Red Pea

34

Me pregunto si esto se está convirtiendo en un partido de golf :

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

Explicación:

sed's p comando es imprimir la línea actual. El comportamiento predeterminado es imprimir la línea actual justo antes de pasar a la siguiente línea (es por eso que sed tiene -nque permitirle desactivarla). Algunos seds más antiguos no tienen punto y coma (creo), por lo que es posible que tenga que hacersed -e p -e p -e p

Awk trabaja con condition {action} pares. Si se omite la acción, el valor predeterminado es imprimir la línea actual si la condición devuelve verdadero. Awk, como muchos lenguajes tipo C, se trata 1como verdadero. (Para completar, si se omite la condición, la acción se ejecutará para cada registro).

Muchas funciones perl aprovechan la variable "predeterminada". Esta línea es equivalente a (en 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, si es así, estás ganando :) ¿Qué hace exactamente 1en awk? Taquigrafía para print $0?
terdon

3
Las declaraciones Awk están formadas por una condición y un bloque, ambos son opcionales, pero uno debe estar presente. La condición predeterminada es 1(verdadera); El bloque predeterminado es equivalente a {print}. Entonces, la declaración 1significaría imprimir el búfer de línea actual ( {print}). ( {print}y {print $0}son casi lo mismo, qed.)
Arcege

Nunca he oído hablar de un sedque no admite punto y coma como terminadores de comando; ¿Realmente hay tal cosa?
Comodín


4

Esto se puede hacer sin que se requiera sed, perlo awk.

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

o usando un ciclo while:

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

Ejemplos

en bucle
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
mientras bucle
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c

Creo que la versión del bucle for se romperá en cualquier línea que contenga espacios en blanco, por lo que debería preferirse el bucle while. De lo contrario, +1 ya que soy un fanático de las soluciones de shell.
evilsoup

@evilsoup: sí, alguien más mencionó esto también en algún código que publiqué en otras preguntas y respuestas. Creo que esa es la principal ventaja de while over for, el while while es tolerante al separador $ IFS y se dividirá al final de la línea, mientras que for se divide en $ IFS.
slm

1

Usando puramente shell:

repeats=4
while read line; do yes $line|head --lines=$repeats; done < infile > outfile

¿Alguien sabe cómo hacer que sí se considere --helpcomo una cadena en lugar de una opción? [considere el caso donde lineestá --helpu otra opción]
user176581

sí,yes -- --help
don_crissti

Usar yesy headsignifica que esto no es "puramente shell"
glenn jackman

1

Esto podría funcionar para usted (GNU sed):

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

Repetirá cada línea 4 veces.

O si lo prefieres:

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

Donde repites cada línea 3 veces más.


1

La respuesta de @potong no funciona con líneas vacías, reemplazar \+con *debería solucionarlo:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.