Перемешать слова в строке

Источником проблемы является то, что перенаправление вывода выполняется пользователем оболочки (yael ), а не sudo echo.

Чтобы запись в /etc/hostsвыполнялась пользователем root, а не пользователем yael-, вы можете использовать следующий формат:

echo "10.10.10.10 yael_host" | sudo tee --append /etc/hosts

или

sudo sh -c "echo '10.10.10.10 yael_host'>>/etc/hosts"
1
06.09.2019, 13:20
7 ответов

POSIX, вы могли бы сделать это с помощью awkотносительно эффективно (определенно эффективнее, чем запускать по крайней мере одну утилиту GNU shufдля каждой строки ввода )как:

awk '
  BEGIN {srand()}
  {
    for (i = 1; i <= NF; i++) {
      r = int(rand() * NF) + 1
      x = $r; $r = $i; $i = x
    }
    print
  }' < your-file

(обратите внимание, что в большинстве реализаций awkзапуск одной и той же команды дважды в одну и ту же секунду, вероятно, даст вам тот же результат, что и случайное начальное число по умолчанию, используемое с srand(), обычно основанное на текущем времени эпохи в секундах. ).

6
27.01.2020, 23:11

Ваша исходная команда может быть упрощена до

shuf -e A B C | tr "\n" " " && echo ""

или

shuffled=( $(shuf -e A B C) ) ; echo ${shuffled[*]}

Который я думаю, немного менее хакерский, а также быстрее по сравнению с моими элементарными тестами.

Если у вас есть файл по адресу ~/test, который содержит

A B C
D E F

Вы можете перетасовывать и отображать каждую строку с помощью следующей команды

while IFS= read -r line; do shuffled=( $(shuf -e $line) ) ; echo ${shuffled[*]} ; done < ~/test

или в виде скрипта:

#!/bin/bash
while IFS= read -r line
    do shuffled=( $(shuf -e $line) )
    echo ${shuffled[*]}
done < ~/test

Где вы можете заменить ~/testна $1для передачи аргументов сценарию.

результат:

B C A
G E F

Как это работает:

shuf -eразбивается на пробелы, а также на новые строки... но только потому, что он будет рассматривать ABC как три аргумента.

так shuf -e A B Cперемешает A B и C но shuf -e "A B C"не будет перемешивать A B и C

Мы можем использовать это для чтения каждой строки в массив, а затем снова распечатать его с помощью echo.

while IFS= read -r line;

Считывает каждую строку в $line, когда она передается с <в этот цикл.

do shuffled=( $(shuf -e $line) )

Создает массив из каждой строки в переменной $shuffled, буквально расширяя shuf -e $lineдо shuf -e A B C.

echo ${shuffled[*]}

повторяет наш массив, по умолчанию печатая каждый элемент с пробелами между ними

< ~/test

передает строки из ~/testв наш цикл.

3
27.01.2020, 23:11

Чтобы передать параметры одной строкой:

shuf -e one two three four— это то, что вам нужно.

shuf -e $(cat <file>) | tr "\n" " "для файла с одной строкой, как в вашем примере.

Для нескольких строк:

while read line; do shuf -e $line | tr "\n" " " && echo \n; done < <file>

1
27.01.2020, 23:11

В то время как как и @steeldriver, я бы использовал подходящий инструмент для обработки текста, такой как perl, для выполнения этой работы , я упомяну хакерский способ с оболочкой zsh:

while read -rA words; do
  print -r -- /(e['reply=($words)']noe['REPLY=$RANDOM'])
done < your-file

Это что-то вроде хака. Мы заканчиваем тем, что используем генерацию имени файла, чтобы иметь возможность использовать квалификатор oglob, который позволяет нам реализовать произвольные порядки сортировки.

Здесь мы используем подстановку /(, которая, как мы знаем, всегда существует ), используем квалификатор eglob, чтобы заменить его содержимым нашего массива, а затем делаем nмерикал oупорядочение на основе выражения REPLY=$RANDOMe.

1
27.01.2020, 23:11

Вот один из способов сделать это, используя «много оклеветанную» оболочку c -:

% foreach line ( "`cat input.txt`" )
     set tokens = ( $line:x )
     foreach ran_idx ( `seq $#tokens | shuf` )
         printf '%s\n' ${tokens[$ran_idx]:q}
     end
end
0
27.01.2020, 23:11

Дано

$ cat file
A B C
D E F
G H I J

затем с помощью shuffleиз списка Perl ::Модуль Util:

$ perl -MList::Util=shuffle -alpe '$_ = join " ", shuffle @F' file
C B A
E D F
I J G H

С bash read -aи shuf(, но очень неэффективно, так как запускает 3 утилиты на строку, 2 из которых не встроены):

$ while read -ra arr; do shuf -e -- "${arr[@]}" | paste -sd ' ' -; done < file
A C B
F E D
J I G H
3
27.01.2020, 23:11

Вот более простой вариант. Поместите вашу строку в массив и используйте shufдля перетасовки

SA=($"A B C")
shuf -e ${SA[@]}
0
19.03.2021, 05:15

Теги

Похожие вопросы