По-моему, один из лучших ресурсов для LVM был Красными Шляпами Руководство администратора LVM, проверьте его.
Это не могло бы быть самым эффективным путем, но он работает:
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
С $m
содержа количество строк.
Этот bash/awk сценарий выбирает строки наугад и поддерживает исходную последовательность в обоих выходных файлах.
awk -v m=4 -v N=$(wc -l <file) -v out1=/tmp/out1 -v out2=/tmp/out2 \
'BEGIN{ srand()
do{ lnb = 1 + int(rand()*N)
if ( !(lnb in R) ) {
R[lnb] = 1
ct++ }
} while (ct<m)
} { if (R[NR]==1) print > out1
else print > out2
}' file
cat /tmp/out1
echo ========
cat /tmp/out2
Вывод, базирующийся ont данные в вопросе.
12345
23456
200
600
========
67891
-20000
20
Как со всеми вещами Unix, существует Утилита для ThatTM.
Программа дня: split
split
разделит файл по-разному, -b
байты, -l
строки, -n
количество выходных файлов. Мы будем использовать -l
опция. Так как Вы хотите выбрать случайные строки и не просто первое m
, мы будем sort
файл случайным образом сначала. Если Вы хотите читать о sort
, обратитесь к моему ответу здесь.
Теперь, фактический код. Это довольно просто, действительно:
sort -R input_file | split -l $m output_prefix
Это сделает два файла, один с m
строки и один с N-m
строки, названные output_prefixaa
и output_prefixab
. Удостовериться m
больший файл, который Вы хотите, или Вы получите несколько файлов длины m
(и один с N % m
).
Если Вы хотите удостовериться, чтобы Вы использовали корректный размер, вот немного кода, чтобы сделать это:
m=10 # size you want one file to be
N=$(wc -l input_file)
m=$(( m > N/2 ? m : N - m ))
sort -R input_file | split -l $m output_prefix
Править: Это привлекло мое внимание что некоторые sort
реализации не имеют a -R
флаг. Если Вы имеете perl
, можно занять место perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
.
sort -R
кажется, только находится в некоторых версиях вида (вероятно, версия гну). Для других платформ я записал инструмент, названный 'randline', который действительно только рандомизирует stdin. Это по beesbuzz.biz/code для любого, кому нужен он. (Я склонен переставлять содержание файла довольно много.)
– fluffy
22.01.2012, 20:49
sort -R
точно не сортирует его вход случайным образом: это группирует идентичные строки. Таким образом, если вход, например. foo
, foo
, bar
, bar
и m=2, затем один файл будет содержать обоих foo
s и другой будет содержать обоих bar
s. GNU coreutils также имеет shuf
, который рандомизирует входные строки. Кроме того, можно выбрать имена выходного файла при помощи head
и tail
вместо split
.
– Gilles 'SO- stop being evil'
23.01.2012, 02:48
Если Вы не возражаете переупорядочивать строки, и у Вас есть GNU coreutils (т.е. на невстроенном Linux или Cygwin, не слишком древнем с тех пор shuf
появившийся в версии 6.0), shuf
(“перестановка”) переупорядочивает строки файла случайным образом. Таким образом, можно переставить файл и диспетчеризировать первые m строки в один файл и остальных в другого.
Нет никакого идеального способа сделать ту отправку. Вы не можете просто объединить в цепочку head
и tail
потому что head
буферизовал бы вперед. Можно использовать split
, но Вы не получаете гибкости относительно имен выходного файла. Можно использовать awk
, конечно:
<input shuf | awk -v m=$m '{ if (NR <= m) {print >"output1"} else {print} }'
Можно использовать sed
, который неясен, но возможно быстрее для больших файлов.
<input shuf | sed -e "1,${m} w output1" -e "1,${m} d" >output2
Или можно использовать tee
копировать данные, если Ваша платформа имеет /dev/fd
; это в порядке, если m является маленьким:
<input shuf | { tee /dev/fd/3 | head -n $m >output1; } 3>&1 | tail -n +$(($m+1)) >output2
Портативно, можно использовать awk для диспетчеризации каждой строки в свою очередь. Обратите внимание, что awk не очень хорош при инициализации его генератора случайных чисел; случайность только определенно не не подходит для криптографии, но и даже очень хороша для численного моделирования. Семя будет тем же для всех awk вызовов на любом системном скручивании жгутов один второй период.
<input awk -v N=$(wc -l <input) -v m=3 '
BEGIN {srand()}
{
if (rand() * N < m) {--m; print >"output1"} else {print >"output2"}
--N;
}'
При необходимости в лучшей случайности можно сделать то же самое в Perl, который отбирает его RNG прилично.
<input perl -e '
open OUT1, ">", "output1" or die $!;
open OUT2, ">", "output2" or die $!;
my $N = `wc -l <input`;
my $m = $ARGV[0];
while (<STDIN>) {
if (rand($N) < $m) { --$m; print OUT1 $_; } else { print OUT2 $_; }
--$N;
}
close OUT1 or die $!;
close OUT2 or die $!;
' 42
awk
пример: -v N=$(wc -l <file) -v m=4
... и это только печатает "случайную" строку, когда случайное значение является меньше, чем $m
, вместо печати $m
случайные строки... Это кажется этим perl
может делать то же самое с рэндом, но я не знаю perl
достаточно хорошо закончить ошибку компиляции: синтаксическая ошибка в-e строке 7, рядом"), печатают"
– Peter.O
23.01.2012, 06:49
shuf
пример.
– Peter.O
24.01.2012, 01:03
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
результаты для выводов ТЕСТА 1-2 5000 5 000 (пользы), но для ТЕСТА 3-4 5000 4539 (не хорош).. differnece варьируется в зависимости от включенных размеров файла... Вот ссылка на мой тестовый код
– Peter.O
24.01.2012, 06:00
head
чтения вперед; то, что это читает вперед и не распечатывает, отбрасывается. Я обновил свой ответ с менее изящным, но (я довольно уверен), правильные решения.
– Gilles 'SO- stop being evil'
24.01.2012, 17:10
Принятие m = 7
и N = 21
:
cp ints ints.bak
for i in {1..7}
do
rnd=$((RANDOM%(21-i)+1))
# echo $rnd;
sed -n "${rnd}{p,q}" 10k.dat >> mlines
sed -i "${rnd}d" ints
done
Примечание: Если Вы заменяете 7
с переменной как $1
или $m
, необходимо использовать seq
, не {from..to}
- нотация, которая не делает переменного расширения.
Это работает путем удаления линию за линией из файла, который становится короче и короче, таким образом, номер строки, который может быть удален, должен стать меньшим и меньшим.
including them
но исходные строки также - поэтому including
, нет consisting of
, и не использование only
, но я предполагаю, что Ваша интерпретация, что означал user288609. Я скорректирую свой сценарий соответственно.
– user unknown
22.01.2012, 16:39
+1
в неправильном месте. Это должно быть rnd=$((RANDOM%(N-i)+1))
где N=21 в Вашем примере.. Это в настоящее время вызывает sed
отказать когда rnd
оценен к 0
... Кроме того, это не масштабируется очень хорошо со всей той перезаписью файла. например, 123 секунды для извлечения 5 000 случайных строк из 10 000 файлов строки по сравнению с 0,03 секундами для более прямого метода...
– Peter.O
23.01.2012, 14:04
sort -R
заботится о случайности. Не уверенный, если Вы downvoted ответ для этого, но ищут его в странице справочника сначала. – Rob Wouters 22.01.2012, 16:31sort -R
точно не сортирует его вход случайным образом: это группирует идентичные строки. Таким образом, если вход, например.foo
,foo
,bar
,bar
и m=2, затем один файл будет содержать обоихfoo
s и другой будет содержать обоихbar
s. GNU coreutils также имеетshuf
, который рандомизирует входные строки. Кроме того, Вам не нужен временный файл. – Gilles 'SO- stop being evil' 23.01.2012, 02:45shuf <file> |head -n $m
? – emanuele 19.06.2014, 19:56