Как с помощью grep извлечь предыдущие n символов из файла

Это (наряду со многими другими вещами PageXXX ), определенными в include/linux/page-flags.h, но определение затемнено использованием макросов. См. макрос TESTPAGEFLAGв приведенном выше файле.

В частности, это определение макроса TESTPAGEFLAG:

#define TESTPAGEFLAG(uname, lname, policy)              \
static __always_inline int Page##uname(struct page *page)       \
    { return test_bit(PG_##lname, &policy(page, 0)->flags); }

в сочетании с этим вызовом TESTPAGEFLAG с параметрами обратной записи:

TESTPAGEFLAG(Writeback, writeback, PF_NO_COMPOUND)

3
30.08.2019, 14:21
2 ответа

Поскольку вам нужны перекрывающиеся строки, боюсь, ни один инструмент не может обеспечить это по умолчанию. Необходимо перебрать вход, чтобы найти все перекрывающиеся вхождения. Следующая проблема — жадный характер регулярных выражений :. Вы не найдете опережающего ATCGTA, если можно найти ATCGTAGCTA. Это усложняет выполнение цикла :

.
sed -E ':1
 h;s/(.*TA).*/\1/
 s/.{0,20}TA$/_&/
 s/.*_//p
 g;s/(.*)TA.*/\1/;t1
 d

— первое решение, которое пришло мне в голову. Вывод для примера должен содержать все нужные вам последовательности:

GATGCTGCTATGCTAGATGCTA
TCGTATCGATGCTGCTATGCTA
TAGCATCGTATCGATGCTGCTA
ATCGTAGCTAGCATCGTA
ATCGTAGCTA
ATCGTA

Объяснение :Кажется, проще начать с последнего совпадения, поэтому

  • hсохранить буфер в резервной области для следующего цикла
  • s/(.*TA).*/\1/удаляет все после последнегоTA
  • s/.{0,20}TA$/_&/ставит подчеркивание в качестве маркера в начале последовательности, которую вы хотите получить
  • s/.*_//pудаляет все до маркера и печатает последовательность
  • Чтобы подготовиться к следующему циклу, gвосстанавливает сохраненный шаблон, а s/(.*)TA.*/\1/удаляет последний TAи последующие, чтобы его больше нельзя было найти
  • наконец, t1начинается с :1, в то время как последовательность была найдена.
  • dподавляет ложный вывод в конце
1
27.01.2020, 21:24

Может быть, есть способ получить перекрывающиеся совпадения сgrep -o(Я не знаю ни одного, даже с grep -Po), но тем временем вы можете использоватьawk:

echo ATCGTAGCTAGCATCGTATCGATGCTGCTATGCTAGATGCTAGT |
awk '{
   i=0; for(s=$0; j = index(s,"TA"); s = substr($0, i + 1))
            print ((i += j) > 20) ? substr($0, i - 20, 22) : substr($0, 1, i+1)
}'

ATCGTA
ATCGTAGCTA
ATCGTAGCTAGCATCGTA
TAGCATCGTATCGATGCTGCTA
TCGTATCGATGCTGCTATGCTA
GATGCTGCTATGCTAGATGCTA

Если вам не нужны более короткие совпадения с начала строки, упростите их до:

echo ATCGTAGCTAGCATCGTATCGATGCTGCTATGCTAGATGCTAGT |
awk '{
    i=0; for(s=$0; j = index(s,"TA"); s = substr($0, i + 1))
             if((i += j) > 20) print substr($0, i - 20, 22)
}'

TAGCATCGTATCGATGCTGCTA
TCGTATCGATGCTGCTATGCTA
GATGCTGCTATGCTAGATGCTA

То же самое вperl:

echo ATCGTAGCTAGCATCGTATCGATGCTGCTATGCTAGATGCTAGT |
perl -nle 'print $-[0] > 20 ? substr $_, $-[0]-20, 22 : substr $_, 0, $+[0] while /TA/g'

ATCGTA
ATCGTAGCTA
ATCGTAGCTAGCATCGTA
TAGCATCGTATCGATGCTGCTA
TCGTATCGATGCTGCTATGCTA
GATGCTGCTATGCTAGATGCTA


echo ATCGTAGCTAGCATCGTATCGATGCTGCTATGCTAGATGCTAGT |
perl -nle 'pos() -= 21, print $1 while /(.{20}TA)/g'

TAGCATCGTATCGATGCTGCTA
TCGTATCGATGCTGCTATGCTA
GATGCTGCTATGCTAGATGCTA

При использованииmawk(по умолчанию в Debian -, например ), версия awkбудет быстрее.

Хоть это и подходит для демонстрации sedмастерства, любое sedрешение должно быть на много порядков медленнее, чем perlили awk.

0
27.01.2020, 21:24

Теги

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