Источником проблемы является то, что перенаправление вывода выполняется пользователем оболочки (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"
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()
, обычно основанное на текущем времени эпохи в секундах. ).
Ваша исходная команда может быть упрощена до
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
в наш цикл.
Чтобы передать параметры одной строкой:
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>
В то время как как и @steeldriver, я бы использовал подходящий инструмент для обработки текста, такой как perl
, для выполнения этой работы , я упомяну хакерский способ с оболочкой zsh
:
while read -rA words; do
print -r -- /(e['reply=($words)']noe['REPLY=$RANDOM'])
done < your-file
Это что-то вроде хака. Мы заканчиваем тем, что используем генерацию имени файла, чтобы иметь возможность использовать квалификатор o
glob, который позволяет нам реализовать произвольные порядки сортировки.
Здесь мы используем подстановку /
(, которая, как мы знаем, всегда существует ), используем квалификатор e
glob, чтобы заменить его содержимым нашего массива, а затем делаем n
мерикал o
упорядочение на основе выражения REPLY=$RANDOM
e
.
Вот один из способов сделать это, используя «много оклеветанную» оболочку 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
Дано
$ 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
Вот более простой вариант. Поместите вашу строку в массив и используйте shuf
для перетасовки
SA=($"A B C")
shuf -e ${SA[@]}