Respostas:
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 ser executado diretamente onde definido como
duplicator dog cat bird whale
Você poderia usar sed
:
sed -r 's/(\S+)/\1 \1/g' filename
Se você deseja 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 -i
opção para salvar as alterações no arquivo no local.)
Ou, como sugerido por terdon :
perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename
Citação de perlvar
:
@F
A matriz
@F
contém os campos de cada linha lida quando o modo de divisão automática está ativado. Veja perlrun para o-a
switch. Essa matriz é específica do pacote e deve ser declarada ou ter um nome completo do pacote, se não estiver no pacote principal quando estiver sendo executadostrict 'vars'
.
sed -r 's/\S+/& &/g'
.
-a
:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
O que seria isso sem uma awk/gawk
resposta:
$ 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"
for(i=1;i<=NF;++i) printf "%s %s ",$i,$i;
é mais curto e mais legível, IMHO.
s="dog cat bird wale"
ss=$( tr ' ' '\n' <<< "$s" | sed p | tr '\n' ' ' )
echo "$ss"
dog dog cat cat bird bird wale wale
sed -n 'p;p'
- achei mais transparente o que estava fazendo.
Se você tem sua string em uma variável, digamos foo="dog cat bird whale"
, você pode 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 o read
e echo
aconteça no mesmo subshell e, portanto, possam compartilhar variáveis. Sem eles, echo
apenas 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 -o
sinalizador de join
permite definir o formato de saída. Aqui, estou dizendo para imprimir o 1º campo do 1º arquivo ( 1.1
), seguido pelo 2º campo do 1º arquivo ( 1.2
) etc. Dessa forma, cada campo do 1º arquivo é impresso duas vezes. No entanto, join
foi projetado para, bem, unir duas linhas de entrada em um campo comum. Então, eu também passo uma linha em branco ( <(echo)
) e depois a ignoro. Os -j
conjuntos do campo de associação, definindo-o como um que não existe (5º) faz com que join
para imprimir toda a linha.
Se você não se importa com espaço em branco ou a ordem de entrada, 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 na matriz @k
e depois será impresso @k
. Se você não precisar da nova linha à direita, 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 -0
opção define o separador de registros de entrada (como um número hexadecimal ou octal, consulte aqui para conversões). Aqui, estou configurando para octal, 040
que é um espaço. As -p
marcas perl
imprimem cada "linha" de entrada e, como definimos o separador de registros como espaço, as linhas agora são definidas por espaços, para que cada campo seja 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; portanto, o script acima passa por cada campo e o anexa a si próprio. Feito isso, imprimimos a linha ( 1;
é apenas uma abreviação para impressão).
Agora, para uma python
resposta:
Na linha de comando:
$ python -c "import sys; s=sys.argv[1:]; print(' '.join(j for i in zip(s,s)for j in i));" dog cat bird whale
Partida stdin:
$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"
O resultado nos dois casos:
dog dog cat cat bird bird whale whale
Outra abordagem, também usando apenas bash builtins
$ string="dog cat bird whale"
$ twix() { while [[ ! -z $1 ]]; do printf "%s %s " $1 $1; shift; done; }
$ twix $string
dog dog cat cat bird bird whale whale
Não vejo nenhum benefício comparado à resposta principal, apenas para mostrar uma maneira um pouco diferente, que pode ser mais adequada para alguns propósitos.
echo
também é um shell embutido no Bash (teste type echo
).