Как обрабатывать каждую строку в bash

Я хотел бы печатать нечетные строки (1,3,5,7..) без каких-либо изменений, но даже строки (2,4,6,8) обрабатываются с конвейером, начинающимся с grep. Я хотел бы написать все в новый файл (нечетные строки без каких-либо изменений и новые значения для четных строк).

Я знаю, как печатать каждую строку в awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print; }' file.fasta

Однако для четных строк я не хочу использовать {print; }, но вместо этого хочу использовать мой grep-конвейер.

Будет оценен совет. Большое спасибо.

Ответ 1

Если вы планируете сделать простой grep, вы можете покончить с дополнительным шагом и выполнить фильтрацию внутри самого awk, например:

awk 'NR % 2 {print} !(NR % 2) && /pattern/ {print}' file.fasta

Однако, если вы намереваетесь сделать намного больше, а chepner уже указатель вне, вы действительно можете протрубить изнутри awk. Например:

awk 'NR % 2 {print} !(NR % 2) {print | "grep pattern | rev" }' file.fasta

Это открывает канал для команды "pattern | rev" (обратите внимание на окружающие кавычки) и перенаправляет на нее вывод печати. Обратите внимание, что вывод в этом случае может быть не таким, как вы могли ожидать; вы закончите с выводом всех нечетных строк с последующим выходом команды pipeed (которая потребляет четные линии).


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

awk 'NR % 2 {print} !(NR % 2) {print length($0)}' file.fasta

Ответ 2

Вы можете напрямую работать изнутри awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print | "grep -o [actgnACTGN] | wc -l"; }' file.fasta

Помните, однако, что это не сохранит порядок вашего входного файла.

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

Ответ 3

Чтобы выход вашего конвейера отображался в соответствии с вашим AWK-выходом, вам нужно закрыть конвейер на каждой итерации. Это, конечно, очень неэффективно.

awk 'BEGIN{ cmd = "grep -io \047[actgn]\047 | wc -l" } NR % 2 { print } NR % 2 == 0 { print | cmd; close(cmd) }' file.fasta

Вы, очевидно, не хотите считать символы, которые не указаны в указанном списке, поэтому length($0) не будет работать. Это будет работать и должно быть намного быстрее, чем метод трубопровода:

awk 'NR % 2 { print } NR % 2 == 0 {n = split($0, a, /[^actgnACTGN]/); print length($0) - n + 1}' file.fasta

Он работает, разбивая строку, используя символы, которые вы не хотите в качестве разделителей, и вычитаете счетчик подстрок из длины строки и добавляете 1. В сущности, он вычитает количество нежелательных символов из длины строка, оставляющая число желаемых символов в результате.