Перетасовка строк файла с фиксированным начальным числом? - PullRequest
7 голосов
/ 06 мая 2011

Я хочу перетасовать строки файла с фиксированным начальным значением, чтобы я всегда получал один и тот же случайный порядок.Команда, которую я использую, выглядит следующим образом:

sort -R file.txt | head -200 > file.sff

Какое изменение я могу сделать, чтобы оно сортировалось с фиксированным случайным начальным числом?

Ответы [ 3 ]

7 голосов
/ 31 января 2017

Реализация sort в GNU имеет аргумент --random-source.Передача этого аргумента с именем файла с известным содержимым приведет к надежному набору выходных данных.

См. Документацию Случайные источники в руководстве по GNU coreutils, которое содержит следующий пример реализациии пример:

get_seeded_random()
{
  seed="$1"
  openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt \
    </dev/zero 2>/dev/null
}

shuf -i1-100 --random-source=<(get_seeded_random 42)

Поскольку GNU sort также является частью coreutils, там применима и соответствующая документация:

sort --random-source=<(get_seeded_random 42) -R file.txt | head -200 > file.sff
1 голос
/ 31 января 2017

Вам может не потребоваться использование внешних инструментов, таких как sort, параметры и использование которых могут различаться в зависимости от вашей операционной системы. Bash имеет внутренний генератор случайных чисел, доступный через переменную $RANDOM. Обычная практика - заполнять генератор, устанавливая переменную, например так:

RANDOM=$$

или

RANDOM=$(date '+%s')

и т.д.. Но, конечно, вы также можете использовать предсказуемое начальное число, чтобы получить предсказуемые неслучайные результаты:

$ RANDOM=12345; echo $RANDOM
28207
$ RANDOM=12345; echo $RANDOM
28207

Чтобы переупорядочить строки отображаемого файла случайным образом, вы можете прочитать файл в массив, используя mapfile:

$ mapfile -t a < source.txt

Затем просто переписать индексы массива:

$ for i in ${!a[@]}; do a[$((RANDOM+${#a[@]}))]="${a[$i]}"; unset a[$i]; done

При чтении неассоциативного массива bash естественным образом упорядочивает элементы в порядке возрастания значения индекса.

Обратите внимание, что в индекс new для каждой строки добавлено количество элементов массива, чтобы избежать коллизий в этом диапазоне. Это решение все еще подвержено ошибкам - нет гарантии, что $RANDOM выдаст уникальные числа. Вы можете уменьшить этот риск с помощью дополнительного кода, который проверяет предыдущее использование каждого индекса, или уменьшить риск с помощью сдвига битов:

... a[$(( (RANDOM<<15)+RANDOM+${#a[@]} ))]= ...

Это превращает ваши значения индекса в 30-битное целое число без знака вместо 15-битного целое число без знака.

0 голосов
/ 06 мая 2011

Если вы случайно перетасовываете строки, вы не сортируете. Я не видел sort с --random-source подсказкой раньше. Было бы интересно, если бы он существовал. Однако это не сортировка строк в фиксированном порядке.

Я полагаю, что вам придется написать программу для этого, и я не думаю, что Bash вполне может это сделать.

На самом деле, возможно. Переменная среды $ RANDOM выбирает случайное число от 0 до 32767. Вы можете назначить начальное число на RANDOM, и последовательность случайных чисел будет появляться снова и снова. Вы можете использовать алгоритм раздачи карт . Прочитайте каждую строку в массиве Bash, затем используйте алгоритм раздачи карт, чтобы выбрать каждую строку.

Я не собираюсь писать тестовую программу - особенно на Bash, но вы должны понять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...