Ответы:
Добавление в семейство решений :-).
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
просто напечатать пустую строку.
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
Объяснение:-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
Из стандартного ввода:
$ 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
).