Risposte:
Aggiungendo alla famiglia di soluzioni :-).
duplicator.sh
:
for i; do echo -n "$i $i "; done; echo
Rendi eseguibile e ora:
$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale
In alternativa come funzione shell, ad esempio per essere riutilizzabile all'interno di uno script:
duplicator() {
for i; do echo -n "$i $i "; done; echo
}
che può quindi essere eseguito direttamente dove definito come
duplicator dog cat bird whale
Puoi usare sed
:
sed -r 's/(\S+)/\1 \1/g' filename
Se si desidera salvare le modifiche sul file sul posto, dire:
sed -i -r 's/(\S+)/\1 \1/g' filename
Puoi anche usare perl
:
perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename
(Aggiungi l' -i
opzione per salvare le modifiche al file sul posto.)
Oppure, come suggerito da Terdon :
perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename
Citando da perlvar
:
@F
L'array
@F
contiene i campi di ciascuna riga letta quando è attivata la modalità autosplit. Vedi perlrun per l'-a
interruttore. Questo array è specifico del pacchetto e deve essere dichiarato o assegnato un nome pacchetto completo se non in pacchetto principale quando è in esecuzione sottostrict 'vars'
.
sed -r 's/\S+/& &/g'
.
-a
:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
Cosa sarebbe questo senza una awk/gawk
risposta:
$ 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 una riga di chiusura è 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;
è sia più breve che più leggibile, 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'
- ho pensato che fosse più trasparente su ciò che sta facendo.
Se hai la tua stringa in una variabile, ad esempio foo="dog cat bird whale"
, potresti fare:
Bash 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
Spiegazione: Le parentesi sono necessarie affinché la read
e echo
avvengano nella stessa sottostruttura e possano quindi condividere le variabili. Senza di essi, echo
si stamperebbe solo una riga vuota.
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
Spiegazione: Il -o
flag di join
consente di impostare il formato di output. Qui, gli sto dicendo di stampare il 1 ° campo del 1o file ( 1.1
), seguito dal 2o campo del 1o file ( 1.2
) ecc. In questo modo ogni campo del 1o file viene stampato due volte. Tuttavia, join
è progettato per unire due linee di input su un campo comune. Quindi, gli passo anche una riga vuota ( <(echo)
) e quindi la ignoro. I -j
set le uniscono campo, impostandolo a uno che non esiste (il 5 °) causa join
per stampare l'intera linea.
Se non ti interessa lo spazio bianco o l'ordine di input, puoi farlo
$ 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
Spiegazione:
-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.
Lo script sopra salverà ogni campo (da @F
) due volte nell'array @k
e quindi stamperà @k
. Se non hai bisogno della nuova riga finale, puoi semplificare
$ echo $foo | perl -ane 'print " $_ $_" for @F'
Perl 2:
$ echo $foo | perl -0040 -pne 'print "$_"' | paste - -
dog dog cat cat bird bird whale whale
Spiegazione: L' -0
opzione imposta il separatore del record di input (come numero esadecimale o ottale, vedere qui per le conversioni). Qui, lo sto impostando su ottale 040
che è uno spazio. I -p
marchi perl
stampano ogni ingresso "line" e poiché abbiamo impostato il separatore di record di spazio, le linee sono ora definiti da spazi, così ogni campo viene stampata due volte.
awk
:
$ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
dog dog cat cat bird bird whale whale
Spiegazione: NF
è il numero di campi, quindi lo script sopra passa attraverso ogni campo e lo aggiunge a se stesso. Una volta fatto, stampiamo la linea ( 1;
è solo una scorciatoia per la stampa).
Ora per una python
risposta:
Dalla riga di 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
Dallo stdin:
$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"
Il risultato in entrambi i casi:
dog dog cat cat bird bird whale whale
Un altro approccio, usando anche solo builtin bash
$ 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
Non vedo alcun vantaggio rispetto alla risposta principale, solo per mostrare un modo leggermente diverso, che potrebbe essere più adatto per alcuni scopi.
echo
è anche una shell integrata in Bash (test type echo
).