unix: получить символы от 10 до 80 в файле

У меня есть файл, содержащий текст, разделенный линией:

GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC 

Из этого я хочу извлечь символы от 10 до 80, так что:

 TGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG GTCGAGCCT 

Я нашел, как считать символы в файле:

  wc -m file 

и как получить количество символов в строке:

  awk '{print substr($0,2,6)}' file 

но я не могу найти способ получить символы от 10 до 80.

Новые строки не считаются символами.

Есть идеи?

Да, это ДНК, из полного генома. Я извлек этот бит ДНК из файла fasta, содержащего различные леса (в этом случае 10 и 11), используя

  awk '/scaffold_10\>/{p=1;next} /scaffold_11/{p=0;exit} p' 

В конечном счете, я хотел бы иметь простую команду, чтобы получить символы от 100 до 800 (или что-то в этом роде) от указанного эшафота.

EDIT: Вопрос продолжается здесь: используйте gff2fasta вместо сценария bash, чтобы получить части ДНК-последовательностей из полного генома

6 Solutions collect form web for “unix: получить символы от 10 до 80 в файле”

Интересно, как обрабатывать линию в файле. Это считается персонажем или нет?

Если мы просто должны взять из байта 10 и напечатать 71 байт (A, C, T, G и linefeed), то решение Sato Katsura является самым быстрым (здесь предполагается GNU dd или совместим для status=none , заменить на 2> /dev/null (хотя это также скроет сообщения об ошибках, если они есть) с другими реализациями):

  dd if=file bs=1 count=71 skip=9 status=none 

Если поток строк следует пропустить, а затем отфильтруйте их с помощью tr -d '\n' :

  tr -d '\n' < file | dd bs=1 count=70 skip=9 status=none 

Если заголовок Fasta должен быть пропущен, он:

  grep -v '^[;>]' file | tr -d '\n' | dd bs=1 count=70 skip=9 status=none 

grep -v '^[;>]' file означает пропустить все строки, которые начинаются с ; или > .

 $ cat file1 GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC 

проверьте длину каждой строки

 $ awk '{print length,$0}' file1 70 GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG 70 GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG 70 GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC 

напечатать символы 10-80

 $ awk '{print substr($0,10,70)}' RS= file1 TGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG GTCGAGCC 

Это предполагает, что вход не содержит пустую строку ( RS= разрешает режим абзаца, где каждая запись является абзацем (абзацы разделены последовательностями пустых строк)), и это подразумевает загрузку всего файла в память.

Для байтов (так же будет работать и для однобайтовых символов, как в вашем примере):

 dd bs=1 skip=9 count=71 < file 2> /dev/null 

Или более эффективно с GNU dd :

 dd iflag=fullblock,skip_bytes,count_bytes skip=9 count=71 status=none < file 

Для символов, с zsh :

 { IFS= read -ru0 -k9 discard && IFS= read -ru0 -k71 text && printf %s $text } < file 

(ничего не печатает, если в файле меньше 80 символов).

ksh93 и bash имеют параметр -N аналогичный zsh -k , но они не поддерживают символы NUL, а bash – глючит .

С GNU awk :

 awk -v RS='.{1}' -v ORS= 'NR>=10 {print RT}; NR == 80 {exit}' 

Мы используем .{1} as . будучи единственным символом, не будет рассматриваться как регулярное выражение.

Другим вариантом является преобразование в кодировку символов, которая имеет фиксированное количество байтов на символ (и имеет все возможные символы), такие как UTF-32LE, который имеет 4 байта на символ:

 < file iconv -t UTF-32LE | dd bs=4 skip=9 count=71 2> /dev/null | iconv -f UTF-32LE 

Если вы не возражаете, чтобы все содержимое было записано в память, а с развернутой линией, вы можете использовать подстановку команд, чтобы прочитать ее (спасибо Джорджу Василиу за улучшение!)

 data=$( tr -d '\n' < inputfile ) 

затем распечатать с (на основе нуля) 10, для длины 70 байтов:

 printf "%s\n" "${data:9:70}" 
 perl -l -0777pe ' my($start, $stop) = qw/10 80/; $delta = $stop - $start--; (undef, $_, $a) = unpack "A${start}A${delta}A*"; $_ .= $1 while length() - y/\n/\n/ < $delta and $a =~ /(.)/g; ' scaffolded_file_10 

Предполагая, что символы новой строки не значимы для данных, а просто форматирование в файле (код не проверен):

 BEGIN { linesize=70; start=10; end=80; } // { if ((NR>=int(start/linesize) && (NR<=int(end/linesize)) { from = NR==int(start/linesize) ? start % linesize : 0; to = NR==int(end/linesize) ? (end % linesize)-from : linesize+1; print substr($0, from, to); } if (NR==int(end/linesize)) exit; } 
  • `ls / | wc -l` указывает больше строк, чем `ls /` показывает
  • Рекурсивно подсчитывать количество слов в одинаково именованных файлах в разных каталогах
  • jobs / wc: получение странных значений возврата
  • Сохранить количество строк, выводимых в переменную в сценарии оболочки, не потребляя выход
  • Непоследовательное поведение перенаправления ввода
  • grep с количеством отдельных паттернов
  • Почему так медленно?
  • Количество символов имен папок печати
  • Как добавить число слов в файл без добавления общего количества
  • Самый простой способ подсчета строк, соответствующих определенным шаблонам, включая «0», если строка не найдена?
  • Как сделать wc интерпретировать стандарт как список файлов
  • Linux и Unix - лучшая ОС в мире.