Вывод текста между двумя шаблонами регулярных выражений в несколько строк - PullRequest
0 голосов
/ 10 февраля 2019

Я могу выполнить следующую команду, если перенесу myfile в среду с python в наличии:

cat myfile | python filter.py

filter.py

import sys

results = []
for line in sys.stdin:
    results.append(line.rstrip("\n\r")) 

start_match = "some text"
lines_to_include_before_start_match = 4
end_match = "some other text"
lines_to_include_after_end_match = 4

for line_number, line in enumerate(results):
    if start_match in line:
        for x in xrange(line_number-lines_to_include_before_start_match, line_number):
            print results[x]

        print line

        for x in xrange(line_number+1, len(results)):       
            if end_match in results[x]:
                print results[x]

                for z in xrange(x+1, x+lines_to_include_after_end_match):
                    print results[z]

                break
            else:
                print results[x]

        print ""

Но среда, в которой яхочу запустить это в не имеет питона.Является ли мой единственный выбор для преобразования этого в Perl, который, как я знаю, существует в среде?Есть ли простая команда sed или awk для этого?

Я пробовал следующее, но это не совсем дает то, что я ищу, так как пропускает строки +/- 4:

cat myfile | sed -n '/some text/,/some other text/p'

[РЕДАКТИРОВАТЬ: скрипт Python говорит, что lines_to_include_after_end_match равен 4, но на самом деле он возвращает 3]

Ответы [ 3 ]

0 голосов
/ 10 февраля 2019

Это может работать для вас (GNU sed):

sed ':a;$!{N;s/\n/&/4;Ta};/1st text/{:b;n;/2nd text/!bb;:c;N;s/\n/&/4;Tc;b};$d;D' file

Откройте окно из n строк, и, если эти строки содержат 1st text, напечатайте их и продолжайте печатать до 2nd text, затем прочитайте mСледующие строки и распечатать те.В противном случае, если это конец файла, удалите буферизованные строки, иначе удалите первую строку в буфере и повторите.

Если текст совпадения начинается в начале или конце строки, используйте:

sed ':a;$!{N;s/\n/&/4;Ta};/^start/M{:b;n;/end$/M!bb;:c;N;s/\n/&/4;Tc;b};$d;D' file
0 голосов
/ 10 февраля 2019

С sed, пожалуйста, попробуйте:

sed -n "$(($(sed -n '/some text/=' myfile) - 4)),$(($(sed -n '/some other text/=' myfile) + 4))p" myfile
  • Команда sed -n '/some text/=' возвращает номер строки, который соответствует some text.
  • Затем 4 вычитается изчисло выше.
  • Следующая часть sed -n '/some other text/=' работает аналогично, и полученный номер строки добавляется на 4.

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

[Изменить]

Если у вас есть несколько "some other text" в файле, попробуйте вместо этого:

sed -n "$(($(sed -n '/some text/=' myfile) - 4)),\$p" myfile | sed "/some other text/{N;N;N;q}"
0 голосов
/ 10 февраля 2019

Учитывая, что окончания строк \n, вы можете попробовать это:

awk '/some text/{if(l4)printf l4;p=5} /some other text/{e=1} e && p {p--; if (!p) {e=0;l4="";}} !p && !e { l4 = l4 $0 "\n"; sub(/[^\n]*\n(([^\n]*\n){4})/,"\1",l4);} p' file

Обратите внимание, что отметка должна быть 6, если вы хотите напечатать дополнительные 4 строки после окончания матча.
Я думаюВаш собственный код Python будет печатать только еще 3 строки после окончания матча.

Для возможности восстановления введите несколько строк:

awk '/some text/{if(l4)printf l4;p=5} 
    /some other text/{e=1} 
    e && p {p--; if (!p) {e=0;l4="";}} 
    !p && !e { l4 = l4 $0 "\n"; sub(/[^\n]*\n(([^\n]*\n){4})/,"\1",l4);} 
    p' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...