Как случайным образом извлечь подстроку из 200 символов из фаста-файла

С sftpвы не изменяете файл на месте, вы копируете его на свой компьютер, изменяете его, а затем заменяете его новой версией, которая обязательно затем принадлежит пользователю, под которым вы подключились. Используйте другие средства редактирования. sshfsможет быть вариантом; используйте разумный редактор, например vi; с )по ssh.

1
03.12.2020, 13:53
4 ответа

Чтобы иметь возможность делать множественный быстрый выбор случайных последовательностей длиной 200 -символов, удобно сохранить копию файла fasta без символов новой строки (, исключая также заголовок ).

< file.fasta tail -n+2 | tr -d '\n' > newfile

Таким образом, вы будете случайным образом выбирать начальный символ, не нажимая ни одного символа новой строки и/или не выполняя никаких вычислений для его обработки. Также я предполагаю, чтоwc -c < file(илиwc -mstat -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
1
18.03.2021, 22:45

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'
1
18.03.2021, 22:45

Не очень эффективно, но из вашей последовательности извлекается случайная подстрока длиной 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
18.03.2021, 22:45

Я отмечаю, что указанные размеры файлов составляют миллион строк и 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, :он выполняет само -заполнение при каждом запуске и, похоже, не имеет предвзятости в сгенерированных последовательностях.

0
18.03.2021, 22:45

Теги

Похожие вопросы