Odpowiedzi:
Dodanie do rodziny rozwiązań :-).
duplicator.sh
:
for i; do echo -n "$i $i "; done; echo
Udostępnij plik wykonywalny, a teraz:
$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale
Alternatywnie jako funkcja powłoki, np. W celu wielokrotnego użytku w skrypcie:
duplicator() {
for i; do echo -n "$i $i "; done; echo
}
które można następnie uruchomić bezpośrednio tam, gdzie zdefiniowano jako
duplicator dog cat bird whale
Możesz użyć sed
:
sed -r 's/(\S+)/\1 \1/g' filename
Jeśli chcesz zapisać zmiany w pliku w miejscu, powiedz:
sed -i -r 's/(\S+)/\1 \1/g' filename
Możesz także użyć perl
:
perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename
(Dodaj -i
opcję zapisania zmian w pliku w miejscu).
Lub, jak sugeruje terdon :
perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename
Cytowanie z perlvar
:
@F
Tablica
@F
zawiera pola każdej linii wczytywane, gdy włączony jest tryb automatycznego podziału. Zobacz perlrun dla-a
przełącznika. Ta tablica jest specyficzna dla pakietu i musi być zadeklarowana lub otrzymać pełną nazwę pakietu, jeśli nie jest w pakiecie głównym, gdy jest uruchomionystrict 'vars'
.
sed -r 's/\S+/& &/g'
.
-a
:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
Co by to było bez awk/gawk
odpowiedzi:
$ 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
Jeśli końcowa nowa linia jest ważna:
$ 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;
jest zarówno krótsza, jak i bardziej czytelna, 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'
- myślałem, że to jest bardziej przejrzyste o tym, co robi.
Jeśli masz ciąg w zmiennej, powiedzmy foo="dog cat bird whale"
, możesz zrobić:
Pure Bash:
$ echo "$foo" | (read a b c d && echo "$a $a $b $b $c $c $d $d")
dog dog cat cat bird bird whale whale
Objaśnienie: Nawiasy są potrzebne, aby read
i echo
działały w tej samej podpowłoce, a zatem mogą dzielić zmienne. Bez nich po echo
prostu wydrukowałaby pustą linię.
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
Objaśnienie:-o
Flaga join
pozwala ustawić format wyjściowy. Mówię tutaj, aby wydrukował 1. pole 1. pliku ( 1.1
), a następnie 2. pole 1. pliku ( 1.2
) itd. W ten sposób każde pole 1. pliku jest drukowane dwukrotnie. Jednak join
jest przeznaczony do łączenia dwóch linii wejściowych we wspólnym polu. Więc przekazuję mu również pustą linię ( <(echo)
), a następnie go ignoruję. Te -j
zestawy sprzężenia pola, ustawiając go na taki, który nie istnieje (5th) powoduje join
wydrukowanie całej linii.
Jeśli nie obchodzi Cię spacja lub kolejność wprowadzania, możesz to zrobić
$ 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
Wyjaśnienie:
-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.
Powyższy skrypt zapisze każde pole (z @F
) dwa razy w tablicy, @k
a następnie wydrukuje @k
. Jeśli nie potrzebujesz końcowego znaku nowej linii, możesz to uprościć
$ echo $foo | perl -ane 'print " $_ $_" for @F'
Perl 2:
$ echo $foo | perl -0040 -pne 'print "$_"' | paste - -
dog dog cat cat bird bird whale whale
Objaśnienie:-0
opcja ustawia separator rekordu wejściowego (w systemie szesnastkowym lub liczby ósemkowej, patrz tutaj dla konwersji). Tutaj ustawiam go na ósemkę, 040
która jest przestrzenią. Te -p
marki perl
wydrukować każde wejście „line”, a ponieważ musimy ustawić separator rekordu do przestrzeni, linie są obecnie określone przez przestrzenie, więc każde pole jest drukowany dwukrotnie.
awk
:
$ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
dog dog cat cat bird bird whale whale
Objaśnienie: NF
jest liczbą pól, więc powyższy skrypt przechodzi przez każde pole i dołącza je do siebie. Gdy to zrobisz, drukujemy linię ( 1;
jest po prostu skrótem do wydruku).
Teraz python
odpowiedź:
Z wiersza poleceń:
$ 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
Od standardowego:
$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"
Wynik w obu przypadkach:
dog dog cat cat bird bird whale whale
Nieco przesadzone, ale haskell
odpowiedź:
$ ghc -e "getLine >>= putStrLn . unwords . (concatMap $ replicate 2) . words" <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale
Inne podejście, wykorzystujące tylko wbudowane 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
Nie widzę żadnych korzyści w porównaniu z najlepszą odpowiedzią, aby pokazać nieco inny sposób, który może być bardziej odpowiedni do niektórych celów.
echo
jest także powłoką wbudowaną w Bash (test type echo
).