awk - пропустить первую строку записи

Мои познания в Perl невелики, но, поскольку никто еще не дал ответа на Perl, я попробую.

Передайте ваши данные в виде файла, и он напечатает строки, разделенные табуляцией, с тремя значениями в строке:

perl -e 'while (<>) { $s .= $_; } chomp $s; @arr = split(/\n{2,}/, $s); foreach my $a(@arr) { $a =~ s/Filename: ([^\n]*)\nType: ([^\n]*)\nSize: ([^\n]*)\n.*/$1\t$2\t$3\n/ || next; print "$a"; } ' infile

Результат:

XXXXX   XXX     XXXX
YYYYY   YYY     YYYY

Это немного грубо, но работает, разбивая ввод на абзацы/блоки и затем применяет ваше многострочное регулярное выражение к каждому.

Подробности...

  • while (<>) { $s .= $_; }— Объединить ввод в одну строку.
  • chomp $s— удалить завершающую новую строку из строки.
  • @arr = split(/\n{2,}/, $s)— Разделить строку на последовательные новые строки. Это разбивает его на абзацы/блоки. Храните блоки в массиве.
  • foreach my $a(@arr)— Перебирать каждый элемент массива (блок). Следующие две строки кода применяются к каждому блоку.
  • $a =~ s/Имя файла: ([^\n]*)\nТип: ([^\n]*)\nРазмер: ([^\n]*)\n.*/$1\t$2 \t$3\n/ || next— извлечь значения из трех интересующих полей.Если подстановки не происходит (это означает, что регулярное выражение не соответствует, например, из-за отсутствия значения), пропустите этот блок и перейдите к следующему.
  • print "$a"- Печать результат подстановки: три значения, разделенные табуляцией.

Опять же, я мало пользуюсь Perl, поэтому, вероятно, есть более элегантные решения.

0
04.12.2019, 01:46
3 ответа

IMHO было бы более естественно использовать пустую строку в качестве разделителя записей. В этом «режиме абзаца» awk включает символы новой строки в качестве разделителей полей, поэтому в вашем случае каждая строка записи становится полем. Затем вы можете удалить первое поле, присвоив ему пустую строку; у этого есть хороший побочный эффект переоценки всей записи с заданным разделителем выходных полей: при установке этого значения также на пустую строку, остальные поля объединяются. Затем вы можете просто распечатать длину записи.

awk 'BEGIN {RS="";OFS=""} NR==1 {$1=""; print length}' species_gene

Тестирование с заданными вами входными данными

$ awk 'BEGIN {RS="";OFS=""} NR==1 {$1=""; print length}' species_gene
160
2
28.01.2020, 02:27

length - это не только переменная в Awk, но и функция:

$ awk 'BEGIN {RS=">"} NR==2 {print length($2) + length($3)}' species_gene
160

Вот и все: сложите длины двух полей, а не используйте длину всей записи.

Короче:

$ awk 'BEGIN {RS=">"} NR==2 {print length($2 $3)}' species_gene
160

Одинаково долго:

$ awk 'BEGIN {RS=">"} NR==2 && $0 = length($2 $3)' species_gene
160
1
28.01.2020, 02:27

Возможное незначительное улучшение { {1}} за ваше улучшение до ответа Steeldriver :

awk -vRS=">" -vOFS="" '$1=="genus_1_species_1" {$1=""; print length;}' species_gene

-vRS = ">" эквивалентно BEGIN {RS = " > "} , и аналогично с -vOFS =" ". Мой вклад состоит в том, что эта версия позволяет вам указывать заголовок записи, длина которой, , чтобы вам не приходилось подсчитывать записи.

0
28.01.2020, 02:27

Теги

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