С sftp
вы не изменяете файл на месте, вы копируете его на свой компьютер, изменяете его, а затем заменяете его новой версией, которая обязательно затем принадлежит пользователю, под которым вы подключились. Используйте другие средства редактирования. sshfs
может быть вариантом; используйте разумный редактор, например vi
; с )по ssh
.
Чтобы иметь возможность делать множественный быстрый выбор случайных последовательностей длиной 200 -символов, удобно сохранить копию файла fasta без символов новой строки (, исключая также заголовок ).
< file.fasta tail -n+2 | tr -d '\n' > newfile
Таким образом, вы будете случайным образом выбирать начальный символ, не нажимая ни одного символа новой строки и/или не выполняя никаких вычислений для его обработки. Также я предполагаю, чтоwc -c < file
(илиwc -m
)и stat -c "%s" file
дают один и тот же результат (для обычного контента, локалей и т. д., сначала проверьте его ), поэтому мы используем stat
, который возвращает быстрее.
Для файла с n
символами доступны варианты n-200
. Мы исключаем из возможной начальной позиции последние 200 символов, поскольку они не могут образовывать длинную строку из 200 -символов.
shuf
выбирает случайное число для диапазона 1,n-200
, а комбинация head
и tail
с -c
извлекает строку.
n=$(stat -c "%s" newfile)
r=$(shuf -i1-"$((n-200+1))" -n1)
< newfile tail -c+"$r" | head -c200
Вы можете вызывать его много раз, чтобы получить множество различных независимых случайных выборок, то есть даже одинаковых или перекрывающихся последовательностей.
Если вы хотите, чтобы ваш выбор соответствовал другим критериям, например, не в одной и той же позиции в файле и/или не перекрывался, вам придется анализировать случайные числа из той же команды shuf
(с более высоким значением -n
. ). Или, чтобы не перекрываться, отбрасывайте любые новые значения ближе 200 к существующим.
Если вы хотите выбрать x случайных независимых , но уникальных последовательностей, вы можете начать создавать случайные строки, удалить дубликаты и оставить x из них с помощью head
, например, чтобы получить 10 из них:
while true; do sh test.sh; printf "\n"; done | awk '!seen[$0]++' | head
shuf
случайным образом переставляет строки файла. Если вы хотите выбирать символы случайным образом, используйте fold, чтобы поместить каждый символ в строку.
fold -w 1 file | shuf -n 200 | tr -d '\n'
tr
помещает их обратно в одну строку.
Если вы хотите пропустить заголовок:
tail -n+2 | fold -w 1 | shuf -n 200 | tr -d '\n'
Не очень эффективно, но из вашей последовательности извлекается случайная подстрока длиной 200 байт:
n=200 # number of bytes to extract
num_bytes=$(tail -n+2 file | tr -d '\n' | wc -c) # remove header and newlines, save nr. of bytes
offset=$(shuf -n1 -i0-$(( num_bytes - n ))) # random offset, between 0 and num_bytes - n
tail -n+2 file | tr -d '\n' | # remove header and newlines
dd count="$n" bs=1 skip="$offset" 2>/dev/null # extract substring
Нам нужно заранее знать размер последовательности без заголовка и новой строки, поэтому два прохода по входному файлу необходимы (или временный файл ).
Я отмечаю, что указанные размеры файлов составляют миллион строк и 1 -2 ГБ. Копирование всех данных для удаления новых строк и чтение всех данных для их вырезания с помощью head
и tail
кажется ненужным.
Альтернативой является определение размера файла с помощью:
szFn="$( stat --format=%s "${Fn}" )"
затем сгенерируйте последовательность случайных смещений байтов в файле с помощью:
shuf --input-range=0-$(( szFn - 1 )) -n "${Count}" | sort -n
и повторите эти смещения, чтобы прочитать файл с требуемым смещением поиска:
dd status=none bs=1 skip="${Skip}" count="${Lth}" if="${Fn}"
Этот метод может извлечь 200 одиночных случайных символов в файле размером 10,8 ГБ на жестком диске примерно за 1,5 секунды. (Для сравнения, wc -l
читает файл за 2 мин 28 с. )Вопрос был прояснен с тех пор, как он впервые появился, но этот метод может также извлекать многобайтовые последовательности -. Чтобы иметь дело с новыми строками и т. д., это может занять несколько дополнительных байтов и просто tr -d '\n'
и обрезать эти небольшие разделы.
Из-за ожидаемого размера файлов я проверил некоторые арифметические ограничения. shuf работает с 64 -битным целым числом без знака, а Bash — с 64 -битным целым числом со знаком, как и dd.
Я также провел некоторую статистику по shuf, :он выполняет само -заполнение при каждом запуске и, похоже, не имеет предвзятости в сгенерированных последовательностях.