Как обрабатывать каждую строку в 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. В сущности, он вычитает количество нежелательных символов из длины строка, оставляющая число желаемых символов в результате.