У меня есть список данных, как
12345
23456
67891
-20000
200
600
20
...
Предположим, что размер этого набора данных (то есть строк файла) равен N
. Я хочу случайным образом нарисовать m
линии из этого файла данных. Поэтому на выходе должны быть два файла, один из которых содержит эти m
строки данных, а другой - N-m
строки данных.
Есть ли способ сделать это с помощью команды Linux?
linux
shell
text-processing
user288609
источник
источник
Ответы:
Это может быть не самый эффективный способ, но он работает:
С
$m
указанием количества строк.источник
sort -R
заботится о случайности. Не уверен, что вы отказались от ответа на этот вопрос, но сначала посмотрите его на странице руководства.sort -R
он не сортирует входные данные случайным образом: он группирует одинаковые строки. Таким образом , если вход , напримерfoo
,foo
,bar
,bar
и т = 2, то один файл будет содержать обаfoo
с , а другой будет содержать обаbar
с. GNU coreutils также имеетshuf
, что рандомизирует входные строки. Кроме того, вам не нужен временный файл .shuf <file> |head -n $m
?Этот скрипт bash / awk выбирает строки случайным образом и сохраняет исходную последовательность в обоих выходных файлах.
Вывод, основанный на данных в вопросе.
источник
Как и во всем Unix, есть утилита для этого ТМ .
Программа дня:
split
split
разделит файл по-разному:-b
байты,-l
строки,-n
количество выходных файлов. Мы будем использовать-l
опцию. Так как вы хотите выбрать случайные строки, а не только первыеm
, мы сначала будемsort
случайным образом подавать файл. Если вы хотите прочитать оsort
, обратитесь к моему ответу здесь .Теперь актуальный код. Это довольно просто, на самом деле:
Это создаст два файла, один со
m
строками и один соN-m
строками, с именамиoutput_prefixaa
иoutput_prefixab
. Убедитесь, чтоm
файл большего размера вы хотите, или вы получите несколько файлов длинойm
(и один сN % m
).Если вы хотите убедиться, что вы используете правильный размер, вот небольшой код для этого:
Редактировать: до меня дошло, что в некоторых
sort
реализациях нет-R
флага. Если у вас естьperl
, вы можете заменитьperl -e 'use List::Util qw/shuffle/; print shuffle <>;'
.источник
sort -R
похоже, что только в некоторых версиях сортировки (вероятно, версия GNU). Для других платформ я написал инструмент под названием 'randline', который ничего не делает, кроме рандомизации stdin. Это на beesbuzz.biz/code для всех, кому это нужно. (Я часто перетасовываю содержимое файла.)sort -R
он не сортирует входные данные случайным образом: он группирует одинаковые строки. Таким образом , если вход , напримерfoo
,foo
,bar
,bar
и т = 2, то один файл будет содержать обаfoo
с , а другой будет содержать обаbar
с. GNU coreutils также имеетshuf
, что рандомизирует входные строки. Кроме того, вы можете выбрать имена выходных файлов, используяhead
иtail
вместоsplit
.Если вы не возражаете переупорядочить строки и у вас есть GNU coreutils (то есть на не встроенных Linux или Cygwin, не слишком древних, так как
shuf
появилось в версии 6.0),shuf
(«shuffle») переупорядочивает строки файла случайным образом. Таким образом, вы можете перемешать файл и отправить первые m строк в один файл, а остальные - в другой.Там нет идеального способа сделать эту отправку. Вы не можете просто зацепить
head
иtail
потомуhead
что буферизируете впереди. Вы можете использоватьsplit
, но вы не получаете никакой гибкости в отношении имен выходных файлов. Вы можете использоватьawk
, конечно:Вы можете использовать
sed
, что неясно, но, возможно, быстрее для больших файлов.Или вы можете использовать
tee
для дублирования данных, если ваша платформа имеет/dev/fd
; это нормально, если м мало:В частности, вы можете использовать awk для отправки каждой строки по очереди. Обратите внимание, что awk не очень хорош при инициализации генератора случайных чисел; случайность не только определенно не подходит для криптографии, но даже не очень хороша для численного моделирования. Начальное число будет одинаковым для всех вызовов awk в любой системе за период в одну секунду.
Если вам нужна лучшая случайность, вы можете сделать то же самое в Perl, который прилично заполняет его ГСЧ.
источник
awk
примера:-v N=$(wc -l <file) -v m=4
... и он печатает "случайную" строку только тогда, когда случайное значение меньше$m
, чем печать$m
случайных строк ... Кажется,perl
что с rand можно делать то же самое , но я неperl
недостаточно хорошо знают , чтобы избежать ошибки компиляции: синтаксическая ошибка в -e строке 7, рядом с ") print"shuf
примере.head
cat
Комбо приводит к потере данных в следующем втором испытании 3-4 .... ТЕСТ 1-2{ for i in {00001..10000} ;do echo $i; done; } | { head -n 5000 >out1; cat >out2; }
.. ТЕСТ 3-4{ for i in {00001..10000} ;do echo $i; done; } >input; cat input | { head -n 5000 >out3; cat >out4; }
...wc -l
Результаты для выходов TEST 1-2 являются 5000 5000 (хорошо), но TEST 3-4 это 5000 4539 (не хорошо) .. Различия варьируются в зависимости от размеров файла ... Вот ссылка на мой тестовый кодhead
читает впереди; то, что он читает и не распечатывает, отбрасывается. Я обновил свой ответ менее изящными, но (я вполне уверен) правильными решениями.Предполагая
m = 7
иN = 21
:Примечание. Если вы замените
7
переменную, например,$1
или$m
, вы должны будете использоватьseq
, а не{from..to}
-notation, которая не выполняет расширение переменной.Он работает путем удаления строки за строкой из файла, который становится все короче и короче, поэтому номер строки, которую можно удалить, должен становиться все меньше и меньше.
Это не должно использоваться для более длинных файлов и большого количества строк, поскольку для каждого числа в среднем необходимо прочитать половину файла для 1-го и весь файл для 2-го кода Sed .
источник
including them
но также и исходные строки - следовательноincluding
, нетconsisting of
и не используюonly
, но, думаю, ваша интерпретация такова, что имел в виду пользователь 288609. Я буду корректировать свой сценарий соответственно.+1
в том месте. Это должно бытьrnd=$((RANDOM%(N-i)+1))
где N = 21 в вашем примере. Это в настоящее время вызываетsed
сбой, когдаrnd
оценивается0
. Кроме того, он не очень хорошо масштабируется при переписывании файлов. например, 123 секунды для извлечения 5000 случайных строк из файла с 10000 строк против 0,03 секунды для более прямого метода ...