С -p
(или -n
) однострочник читает строку одновременно; поэтому он просто не может соответствовать многострочным шаблонам. Одно из решений заключается в том, чтобы «налить» весь файл, если он не слишком большой ( см. Конец для построчного решения )
perl -0777 -pe'...' in > out
См. Команду Включает perlrun .
Затем код, показанный в вопросе, содержит несбалансированные скобки и не компилируется. Кроме того, нет причин фиксировать эти .
s, поэтому снимите круглые скобки. Затем шаблон
s/>.+Pseudomyrmex_seminole_D1367...//;
сопоставляет все, начиная с самого первого >
и заканчивая именем, представляющим интерес, поэтому все предыдущие последовательности также сопоставляются и удаляются. Вместо этого сопоставьте, например, >[^>]+...D1367
, чтобы все, что не >
после >
, соответствовало этой фразе.
Наконец, последний .+(?=>)
будет сопоставлять все с очень last >
и, таким образом, регулярное выражение удалит все последующие последовательности, а не то, что вы хотите в соответствии с описанием. Вместо этого ограничьте его до первого следующего >
, либо сделав его «нежадным» с .+?(?=>)
или, проще, с [^>]+
.
Все исправлено
perl -0777 -pe's/>[^>]+?Pseudomyrmex_seminole_D1367[^>]+//' in > out
Обратите внимание, что модификатор /s
теперь не нужен, поскольку его цель - заставить .
соответствовать символу новой строки, и здесь нам это не нужно, поскольку [^>]
также соответствует символу новой строки (что-нибудь другое чем >
). Квантификатор +?
предназначен для (надеюсь) предотвращения обратного отслеживания каждой целой последовательности, которая не соответствует.
Или с вашим первоначальным использованием lookahead
perl -0777 -pe's/>[^>]+?Pseudomyrmex_seminole_D1367.+?(?=>)//s' in > out
Они работают так, как ожидается с вашим образец, а также расширенный пример, который я составил с добавлением дополнительных последовательностей (>...
).
Для справки, и поскольку файл fasta может быть слишком большим, чтобы его можно было перетянуть в строку, здесь это строка за строкой.
Как только вы увидите интересующую линию >...
, установите флаг; выведите строку, если этот флаг не установлен (и если мы не на этой строке). Как только вы доберетесь до следующего >
, снимите флажок (напечатайте и эту строку).
perl -ne'
if (/^>.+?Pseudomyrmex_seminole_D1367/) { $f = 1 }
elsif (not $f) { print }
elsif (/^>/) { $f = 0; print }
' in > out
Я подозреваю, что это также может работать значительно лучше для очень больших файлов.
Регулярное выражение в первом решении нужно просканировать каждую последовательность целиком, чтобы найти, что она не представляет интерес; только после того, как он достигнет следующего >
, он может решить, что последовательность не совпадает (и, надеюсь, без обратного отслеживания, поскольку +?
остановил бы его, если бы была найдена правильная фраза).
Здесь код в основном проверяет первый символ и флаг.
Так что здесь несравнимо меньшая рабочая нагрузка - но здесь механизм регулярных выражений запускается на каждой строке, и это дорого. Я не могу с уверенностью сказать, как они складываются друг против друга, не пытаясь.