¿Bash Script para repetir cada palabra en una línea?

¿Bash Script para repetir cada palabra en una línea?

Tengo una cadena como:dog cat bird whale

y quiero conseguirdog dog cat cat bird bird whale whale

Todas las palabras están en la misma línea. ¿Alguna idea?

Respuesta1

Sumando a la familia de soluciones :-) .

duplicator.sh:

for i; do echo -n "$i $i "; done; echo

Haz ejecutable, y ahora:

$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale

Alternativamente como función de shell, por ejemplo, para ser reutilizable dentro de un script:

duplicator() {
    for i; do echo -n "$i $i "; done; echo
}

que luego se puede ejecutar directamente donde se define como

duplicator dog cat bird whale

Respuesta2

Podrías usar sed:

sed -r 's/(\S+)/\1 \1/g' filename

Si desea guardar los cambios en el archivo in situ, diga:

sed -i -r 's/(\S+)/\1 \1/g' filename

También podrías usar perl:

perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename

(Agregue la -iopción para guardar los cambios en el archivo in situ).

O, como sugiereterdón:

perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename

Citando deperlvar:

@F

La matriz @Fcontiene los campos de cada línea leída cuando el modo de división automática está activado. Consulte perlrun para el -aconmutador. Esta matriz es específica del paquete y debe declararse o recibir un nombre de paquete completo si no está en el paquete principal cuando se ejecuta bajo strict 'vars'.

Respuesta3

¿Qué sería esto sin una awk/gawkrespuesta?

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }}' <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale 

Si una nueva línea final es importante:

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }} END{print ""}' <<<"dog cat bird whale"

Respuesta4

Si tiene su cadena en una variable, digamos foo="dog cat bird whale", podría hacer:

  • Fiesta pura:

    $ echo "$foo" | (read a b c d && echo "$a $a $b $b $c $c $d $d")
    dog dog cat cat bird bird whale whale
    

    Explicación:Los paréntesis son necesarios para que ready echoocurran en el mismo subnivel y, por lo tanto, puedan compartir variables. Sin ellos, echosimplemente imprimirían una línea en blanco.

  • coreutils:

    $ join -j 5 -o 1.1,1.1,1.2,1.2,1.3,1.3,1.4,1.4 <(echo $foo) <(echo)
    dog dog cat cat bird bird whale whale
    

    Explicación:La -obandera de joinle permite configurar el formato de salida. Aquí, le digo que imprima el primer campo del primer archivo ( 1.1), seguido del segundo campo del primer archivo ( 1.2), etc. De esa manera, cada campo del primer archivo se imprime dos veces. Sin embargo, joinestá diseñado para, bueno, unirsedoslíneas de entrada en un campo común. Entonces, también le paso una línea en blanco ( <(echo)) y luego la ignoro. Establece -jel campo de unión, estableciéndolo en uno que no existe (el quinto) hace joinque se imprima la línea completa.

    Si no le importan los espacios en blanco o el orden de entrada, puede hacerlo

    $ paste <(echo $foo) <(echo $foo)
    dog cat bird wale   dog cat bird wale
    
  • Perla 1:

    $ echo $foo | perl -lane 'push @k, $_,$_ for @F; print "@k"'
    dog dog cat cat bird bird whale whale
    

    Explicación:

    -l: adds a newline to each print call (among other things)
    -a: turns on field splitting, fields are saved as @F
    -n: process input line by line
    -e: give a script as a command line parameter.
    

    El script anterior guardará cada campo (de @F) dos veces en la matriz @ky luego imprimirá @k. Si no necesita la nueva línea final, puede simplificarla a

    $ echo $foo | perl -ane 'print " $_ $_" for @F'
    
  • Perla 2:

    $ echo $foo | perl -0040 -pne 'print "$_"' | paste - - 
    dog dog cat cat bird bird whale whale
    

    Explicación:La -0opción establece el separador de registros de entrada (como un número hexadecimal u octal, consulteaquípara conversiones). Aquí lo estoy configurando en octal, 040que es un espacio. Hacen -pimprimir perlcada "línea" de entrada y como hemos configurado el separador de registros en espacio, las líneas ahora están definidas por espacios, por lo que cada campo se imprime dos veces.

  • awk:

    $ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
    dog dog cat cat bird bird whale whale
    

    Explicación: NFes el número de campos, por lo que el script anterior revisa cada campo y lo agrega a sí mismo. Una vez hecho esto, imprimimos la línea ( 1;es solo una abreviatura de imprimir).

información relacionada