Одна строка на основе файла подмножества и печать других строк до следующей строки - PullRequest
0 голосов
/ 26 января 2019

У меня есть текстовый файл, который содержит несколько записей, которые выглядят как пример ниже:

# 2018 11 21 17 47 37.708756 -34.390213 116.803673 2.6972 0.442474 3.324627 2.840390 0.885880 890
LM01 0.836408 1.00 P
LM01 1.035398 1.00 S
LM03 3.987074 1.00 S
# 2018 11 22 11 58 25.550581 -34.439400 116.750832 2.8513 0.288144 3.306790 2.576028 0.771026 891
LM01 1.664419 1.00 P
LM01 2.471786 1.00 S
LM03 3.536432 1.00 P
# 2018 11 22 14 38 7.190175 -34.447819 116.788727 3.1661 0.577347 2.063253 2.132511 0.608057 892
LM01 1.629825 1.00 P
LM02 3.059825 1.00 P
LM03 3.284825 1.00 P
LM01 2.378885 1.00 S

Мне нужно найти способ, предпочтительно в Bash или Perl, который читает строку с #, поднаборы этой строки основаны на столбце 8 (широта), и, если условие выполнено, печатает остальные строки (например, LM ...), пока не достигнет следующей строки с #.Например, я хочу напечатать только «записи», где столбец 8 <-34.4, и включить строки LM * для этой записи.</p>

Я могу придумать код для чтения каждой # строки, но я не уверен, как запрограммировать "если условие выполнено, выведите строки LM, пока не достигнете следующей # строки".Ожидаемый результат будет:

# 2018 11 22 11 58 25.550581 -34.439400 116.750832 2.8513 0.288144 3.306790 2.576028 0.771026 891
LM01 1.664419 1.00 P
LM01 2.471786 1.00 S
LM03 3.536432 1.00 P
# 2018 11 22 14 38 7.190175 -34.447819 116.788727 3.1661 0.577347 2.063253 2.132511 0.608057 892
LM01 1.629825 1.00 P
LM02 3.059825 1.00 P
LM03 3.284825 1.00 P
LM01 2.378885 1.00 S

Ответы [ 4 ]

0 голосов
/ 28 января 2019

Другой Perl однострочный

  perl -0777 -ne ' while( /(^#.+?)(?=^#|\Z)/gsm ) { print $1 if (split(" ",$1))[7] < -34.4 } '

с входами

$ cat geeb.txt
# 2018 11 21 17 47 37.708756 -34.390213 116.803673 2.6972 0.442474 3.324627 2.840390 0.885880 890
LM01 0.836408 1.00 P
LM01 1.035398 1.00 S
LM03 3.987074 1.00 S
# 2018 11 22 11 58 25.550581 -34.439400 116.750832 2.8513 0.288144 3.306790 2.576028 0.771026 891
LM01 1.664419 1.00 P
LM01 2.471786 1.00 S
LM03 3.536432 1.00 P
# 2018 11 22 14 38 7.190175 -34.447819 116.788727 3.1661 0.577347 2.063253 2.132511 0.608057 892
LM01 1.629825 1.00 P
LM02 3.059825 1.00 P
LM03 3.284825 1.00 P
LM01 2.378885 1.00 S
$ perl -0777 -ne ' while( /(^#.+?)(?=^#|\Z)/gsm ) { print $1 if (split(" ",$1))[7] < -34.4 } ' geeb.txt
# 2018 11 22 11 58 25.550581 -34.439400 116.750832 2.8513 0.288144 3.306790 2.576028 0.771026 891
LM01 1.664419 1.00 P
LM01 2.471786 1.00 S
LM03 3.536432 1.00 P
# 2018 11 22 14 38 7.190175 -34.447819 116.788727 3.1661 0.577347 2.063253 2.132511 0.608057 892
LM01 1.629825 1.00 P
LM02 3.059825 1.00 P
LM03 3.284825 1.00 P
LM01 2.378885 1.00 S
$
0 голосов
/ 26 января 2019

с gawk разделителем записей, perl должно иметь аналог ...

$ awk -v RS='(^|\n)#' '$7<-34.4{printf "%s", rt $0} {rt=RT}' file

# 2018 11 22 11 58 25.550581 -34.439400 116.750832 2.8513 0.288144 3.306790 2.576028 0.771026 891
LM01 1.664419 1.00 P
LM01 2.471786 1.00 S
LM03 3.536432 1.00 P
# 2018 11 22 14 38 7.190175 -34.447819 116.788727 3.1661 0.577347 2.063253 2.132511 0.608057 892
LM01 1.629825 1.00 P
LM02 3.059825 1.00 P
LM03 3.284825 1.00 P
LM01 2.378885 1.00 S

обратите внимание, что вы хотите <, так как знак отрицательный. Поскольку мы используем # в качестве разделителя записей, номер поля на единицу меньше.

Мы определяем разделитель записей как начальный # или после новой строки. Обычно RS находится между записями, но здесь он ведет записи. Поэтому мы фиксируем разделитель совпадающих записей RT и присваиваем переменную, которая будет использоваться в (следующей) записи. Также в RT включена новая строка, поэтому у printf ее нет.

0 голосов
/ 26 января 2019

В строках, не начинающихся с # печать, если флаг включен, в противном случае установить флаг (и печать) в соответствии с условием

perl -wlnE'
    if (/^\s*[^#]/) { say if $y } elsif ((split)[7] < -34.4) { $y=1, say }
' file

При предложенном вводе образца в file это печатает ожидаемыйoutput.

Флаги -lnE могут быть вместо -ne с print вместо say в коде.-w только для предупреждений, часто опускается в одну строку (я всегда использую его).Смотрите Командные переключатели в perlrun

0 голосов
/ 26 января 2019
perl -lane '$matches = ($F[7] < -34.4); print if ($matches .. (/^#/ and not $matches)) and ($matches or not /^#/)'

Это немного запутанно. Вы можете сделать $matches любым выражением в # ... нужных строках. ($matches .. (/^#/ and not $matches)) соответствует всем строкам заголовка вплоть до следующего включающего (потенциально не совпадающего) заголовка, а затем and ($matches or not /^#/) исключает любые несовпадающие заголовки.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...