Відповіді:
Додавання до сімейства рішень :-).
duplicator.sh
:
for i; do echo -n "$i $i "; done; echo
Зробіть виконуваним і тепер:
$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale
Як варіант оболонки, наприклад, для повторного використання в сценарії:
duplicator() {
for i; do echo -n "$i $i "; done; echo
}
який можна запустити безпосередньо там, де визначено як
duplicator dog cat bird whale
Ви можете використовувати sed
:
sed -r 's/(\S+)/\1 \1/g' filename
Якщо ви хочете зберегти зміни у файлі на місці, скажіть:
sed -i -r 's/(\S+)/\1 \1/g' filename
Ви також можете використовувати perl
:
perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename
(Додати -i
опцію для збереження змін у файлі на місці.)
Або, як пропонує тердон :
perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename
Цитуючи perlvar
:
@F
Масив
@F
містить поля кожного рядка, зчитуваного при включенні режиму автоспліт. Дивіться perlrun для-a
вимикача. Цей масив є специфічним для пакета, і йому потрібно оголосити або надати повне ім'я пакета, якщо він не є основним пакетом під час роботи підstrict 'vars'
.
sed -r 's/\S+/& &/g'
.
-a
:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
Що це було б без awk/gawk
відповіді:
$ 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
Якщо важливий завершальний новий рядок:
$ 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;
ІМХО коротший і легший для читання.
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'
- я вважав, що це прозоріше щодо того, що це робиться.
Якщо у вас є рядок у змінній, скажімо foo="dog cat bird whale"
, ви можете зробити:
Чистий баш:
$ echo "$foo" | (read a b c d && echo "$a $a $b $b $c $c $d $d")
dog dog cat cat bird bird whale whale
Пояснення: Дужки необхідні , так що read
і echo
відбувається в тому ж подоболочки і , отже , можуть спільно використовувати змінні. Без них echo
просто надрукували б порожній рядок.
основні:
$ 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
Пояснення:-o
прапор join
дозволяє встановити формат виведення. Тут я говорю це надрукувати 1-е поле 1-го файлу ( 1.1
), а потім 2-е поле 1-го файлу ( 1.2
) тощо. Таким чином, кожне поле 1-го файлу друкується двічі. Однак join
призначений для об'єднання двох вхідних рядків у загальному полі. Отже, я також передаю йому порожній рядок ( <(echo)
), а потім ігнорую його. У -j
наборах З'єднати поле, встановивши його на той , який не існує (5 - й) призводить join
до друку всієї лінії.
Якщо вам не байдуже пробіл або порядок введення, ви можете зробити це
$ 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
Пояснення:
-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.
Сценарій, наведений вище, збереже кожне поле (з @F
) двічі в масиві @k
і потім надрукує @k
. Якщо вам не потрібен новий рядок, ви можете спростити його
$ echo $foo | perl -ane 'print " $_ $_" for @F'
Perl 2:
$ echo $foo | perl -0040 -pne 'print "$_"' | paste - -
dog dog cat cat bird bird whale whale
Пояснення:-0
опція встановлює вхідний роздільник записів (як шістнадцяткове або вісімкове число, см тут для перетворення). Тут я встановлюю його на восьмикутник, 040
який є пробілом. В -p
марці perl
друк кожного входу «лінія» і з тих пір ми встановили роздільник в простір, лінії тепер визначаються пробілами, тому кожне поле друкуються двічі.
awk
:
$ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
dog dog cat cat bird bird whale whale
Пояснення: NF
це кількість полів, тому сценарій вище проходить через кожне поле і додає його до себе. Після цього ми друкуємо рядок ( 1;
це просто скорочення для друку).
Тепер для python
відповіді:
З командного рядка:
$ 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
З stdin:
$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"
Результат в обох випадках:
dog dog cat cat bird bird whale whale
Інший підхід, який також використовує лише 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
Я не бачу жодних переваг порівняно з головною відповіддю, просто щоб показати дещо інший спосіб, який може бути краще підходить для деяких цілей.
echo
також оболонка, вбудована в Bash (тест type echo
).