Bash Script para repetir cada palavra em uma linha?

Bash Script para repetir cada palavra em uma linha?

Eu tenho uma string como:dog cat bird whale

E eu quero conseguirdog dog cat cat bird bird whale whale

Todas as palavras estão na mesma linha. Qualquer ideia?

Responder1

Adicionando à família de soluções :-).

duplicator.sh:

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

Torne executável e agora:

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

Alternativamente como uma função shell, por exemplo, para ser reutilizável dentro de um script:

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

que pode então ser executado diretamente onde definido como

duplicator dog cat bird whale

Responder2

Você poderia usar sed:

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

Se você quiser salvar as alterações no arquivo no local, diga:

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

Você também pode usar perl:

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

(Adicione a -iopção para salvar as alterações no arquivo no local.)

Ou, como sugerido porterdon:

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

Citando deperlvar:

@F

A matriz @Fcontém os campos de cada linha lida quando o modo de divisão automática está ativado. Consulte perlrun para a -aopção. Este array é específico do pacote e deve ser declarado ou receber um nome completo do pacote se não estiver no pacote main quando executado em strict 'vars'.

Responder3

O que seria disso sem uma awk/gawkresposta:

$ 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 

Se uma nova linha final for importante:

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

Responder4

Se você tiver sua string em uma variável a, digamos foo="dog cat bird whale", você poderia fazer:

  • Festa 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
    

    Explicação:Os parênteses são necessários para que reade echoaconteçam no mesmo subshell e possam, portanto, compartilhar variáveis. Sem eles, echoapenas imprimiria uma linha em branco.

  • 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
    

    Explicação:O -osinalizador joinpermite definir o formato de saída. Aqui estou dizendo para imprimir o 1º campo do 1º arquivo ( 1.1), seguido do 2º campo do 1º arquivo ( 1.2) etc. Dessa forma cada campo do 1º arquivo é impresso duas vezes. No entanto, joinfoi projetado para, bem, juntar-sedoislinhas de entrada em um campo comum. Então, também passo uma linha em branco ( <(echo)) e depois ignoro. O -jdefine o campo de junção, definindo-o como um que não existe (o 5º) faz com joinque a linha inteira seja impressa.

    Se você não se importa com os espaços em branco ou com a ordem de entrada, você pode fazer

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

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

    Explicação:

    -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.
    

    O script acima salvará cada campo (de @F) duas vezes no array @ke depois imprimirá @k. Se você não precisar da nova linha final, poderá simplificar para

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

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

    Explicação:A -0opção define o separador de registros de entrada (como um número hexadecimal ou octal, consulteaquipara conversões). Aqui, estou configurando para octal, 040que é um espaço. O -pfaz perlimprimir cada "linha" de entrada e como definimos o separador de registros como espaço, as linhas agora são definidas por espaços, então cada campo é impresso duas vezes.

  • awk:

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

    Explicação: NFé o número de campos, então o script acima passa por cada campo e o anexa a si mesmo. Feito isso, imprimimos a linha ( 1;é apenas uma abreviação de impressão).

informação relacionada