Через grep
, если несколько раз подряд:
grep -oP '(?<=<td>).*?(?=</td>)' infile.txt
1
6
Через awk
и то же самое, если несколько раз подряд:
awk -v FS="(<td>|</td>)" '{for(i=2;i<=NF;i+=2) print $I}' infile.txt
Предположим, что вы делаете это вbash
:
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
printf '%s\n' "${sequence:i:3}"
done
Это повторяется по всей длине последовательности, по три пары оснований -за раз. На каждой итерации печатается следующая группа из трех оснований.
Чтобы поместить их в массив, seq
вместо того, чтобы распечатывать их:
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
seq+=( "${sequence:i:3}" )
done
Это дает вам массив seq
. Отдельные элементы массива доступны как "${seq[0]}"
, "${seq[1]}"
и т. д.
Чтобы получить две другие рамки считывания , измените цикл так, чтобы он начинался с 1 или 2.
Если ваша строка не содержит пробелов или новых строк, вы можете использовать grep
для разделения строки и создания массива:
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
seq=( $(printf '%s' "$sequence" | grep -o... ) )
или используйте fold
вместоgrep
:
seq=( $(printf '%s' "$sequence" | fold -b3 ) )
По сравнению с grep
последний одиночный символ(G
)также будет элементом массива.
Примечание.:Если ваша строка содержит *
, в некоторых случаях это может привести к проблемам. Например. если вы получите seq=( AT* ATA ATG )
и у вас есть имена файлов, начинающиеся с AT
в текущем рабочем каталоге, вместо этого они будут расширены до имен файлов. Вы можете использовать set -o noglob
для предотвращения подстановки.
Лучшая альтернатива:использовать readarray
вместоseq=(...)
:
readarray seq < <(printf '%s' "$sequence" | fold -b3 )
(кредиты для этого @Kusalananda)
В bash
обработка длинных строк с циклами и индексами может быть очень медленной, в качестве альтернативы вы можете read
построить строку и построить массив:
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
declare -a seq=( "" )
while read -n 3 -r triple ; do seq+=( "$triple" ); done <<< "$sequence"
declare -p seq
Массив создается с индексом 0 пустой строки, поэтому ваши индексы начинаются с 1, как и требовалось.
Это работает следующим образом: используйте "read -n 3
" для чтения трех символов за раз в переменную triple
, добавьте ее в массив (+=
), используя перенаправление <<<
для представления последовательности в stdin
. ]. read
обрабатывает случаи, когда ввод не кратен 3.
(Как показано выше, это хорошо для чтения неразрывных последовательностей букв — это не универсальная процедура «разделения», поскольку она не имеет специальной обработки пробелов, escape-символов, нулевых байтов и т. д. Если вы установите IFS=""
, то read
сохранит пробелы во входных данных. Если вам нужно удалить пробелы из ввода, вы можете использовать ... <<< ${sequence// /}
.
Это частный случай более общей задачи Разделить строку на массив в Bash , где вы также можете прочитать обо всех интересных ловушках для неосторожного программиста.)