Respuestas:
Agregando a la familia de soluciones :-).
duplicator.sh
:
for i; do echo -n "$i $i "; done; echo
Hacer ejecutable, y ahora:
$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale
Alternativamente como una 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
Podrías usar sed
:
sed -r 's/(\S+)/\1 \1/g' filename
Si desea guardar los cambios en el archivo en el lugar, diga:
sed -i -r 's/(\S+)/\1 \1/g' filename
También puedes usar perl
:
perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename
(Agregue la -i
opción para guardar los cambios en el archivo en el lugar).
O, como lo sugiere terdon :
perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename
Citando de perlvar
:
@F
La matriz
@F
contiene los campos de cada línea leída cuando el modo de división automática está activado. Ver perlrun para el-a
cambio. 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 bajostrict 'vars'
.
sed -r 's/\S+/& &/g'
.
-a
:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
¿Qué sería esto sin una awk/gawk
respuesta?
$ 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 de terminación es 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;
es más corto y más legible, en mi humilde opinión.
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'
, pensé que era más transparente sobre lo que estaba haciendo.
Si tiene su cadena en una variable, por ejemplo foo="dog cat bird whale"
, podría hacer:
Golpe puro:
$ 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 read
y echo
suceda en la misma subshell y, por lo tanto, puedan compartir variables. Sin ellos, echo
simplemente 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: El -o
indicador de le join
permite establecer 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 esta manera, cada campo del primer archivo se imprime dos veces. Sin embargo, join
está diseñado para, bueno, unir dos líneas de entrada en un campo común. Entonces, también le paso una línea en blanco (<(echo)
) y luego lo ignoro. Los -j
conjuntos se unen las de campo, estableciendo que a uno que no existe (la quinta) hace que join
imprimir toda la línea.
Si no le importa el espacio en blanco o el orden de entrada, puede hacer
$ 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
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.
La secuencia de comandos anterior guardará cada campo (de @F
) dos veces en la matriz @k
y luego imprimirá @k
. Si no necesita la nueva línea final, puede simplificar
$ echo $foo | perl -ane 'print " $_ $_" for @F'
Perl 2:
$ echo $foo | perl -0040 -pne 'print "$_"' | paste - -
dog dog cat cat bird bird whale whale
Explicación: La -0
opción establece el separador de registro de entrada (como un número hexadecimal u octal, consulte aquí las conversiones). Aquí, lo estoy configurando en octal, 040
que es un espacio. Las -p
marcas perl
imprimen cada "línea" de entrada y dado que hemos establecido 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: NF
es el número de campos, por lo que el script anterior recorre cada campo y lo agrega a sí mismo. Una vez hecho esto, imprimimos la línea ( 1;
es solo una abreviatura para imprimir).
Ahora por un python
respuesta:
Desde la línea 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
De stdin:
$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"
El resultado en ambos casos:
dog dog cat cat bird bird whale whale
Ligeramente exagerado, pero una haskell
respuesta:
$ ghc -e "getLine >>= putStrLn . unwords . (concatMap $ replicate 2) . words" <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale
Otro enfoque, que también usa solo 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
No veo ningún beneficio en comparación con la respuesta principal, solo para mostrar una forma ligeramente diferente, que podría ser más adecuada para algunos propósitos.
echo
También es un shell incorporado en Bash (prueba type echo
).