Bash-скрипт для повторения каждого слова в строке?

Bash-скрипт для повторения каждого слова в строке?

У меня есть строка вроде:dog cat bird whale

И я хочу получитьdog dog cat cat bird bird whale whale

Все слова в одной строке. Есть идеи?

решение1

Пополнение в семействе решений :-) .

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

решение2

Вы можете использовать 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. Этот массив зависит от пакета и должен быть объявлен или ему должно быть дано полное имя пакета, если он не находится в package main при запуске под strict 'vars'.

решение3

Что бы это было без 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"

решение4

Если у вас есть строка в переменной, скажем 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
    
  • Перл 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'
    
  • Перл 2:

    $ echo $foo | perl -0040 -pne 'print "$_"' | paste - - 
    dog dog cat cat bird bird whale whale
    

    Объяснение:Опция -0устанавливает разделитель входных записей (в виде шестнадцатеричного или восьмеричного числа, см.здесьдля преобразований). Здесь я устанавливаю его на восьмеричное, 040что является пробелом. -pMakes 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;это просто сокращение для print).

Связанный контент