САС: адресация двух строк перед матчем

Выведите строку, которая находится за 2 строки до соответствия (шаблон).

Я попробовал следующее:

sed -n ': loop
/.*/h
:x
{n;n;/cen/p;}
s/./c/p
t x
s/n/c/p
t loop
{g;p;}
' datafile

6 ответов

Решение

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

sed -n ':a;$!{N;s/\n/&/2;Ta};/^PATTERN\'\''/MP;$!D' file

Это напечатает строку за 2 строки до PATTERN по всему файлу.

Сценарий:

  sed -n "1N;2N;/XXX[^\n]*$/P;N;D"

работает следующим образом:

  • Прочитайте первые три строки в пространство образца, 1N;2N
  • Поиск тестовой строки XXX где-нибудь в последней строке, и если найдено, выведите первую строку пространства шаблона, P
  • Добавить следующую строку ввода в пространство образца, N
  • Удалить первую строку из пространства шаблона и перезапустить цикл без нового чтения, Dотмечая, что 1N;2N больше не применимо

Этот с grep, немного более простое решение и легко читаемый [Однако нужно использовать один канал]:grep -B2 'pattern' file_name | sed -n '1,2p'

Если вы можете использовать awk попробуй это:

awk  '/pattern/ {print b} {b=a;a=$0}' file

Это напечатает две строки до pattern

Я проверил вашу команду sed, но результат странный (и, очевидно, неправильный), и вы не дали никакого объяснения. Вам нужно будет сохранить три строки в буфере (именуемый удерживающим пространством), выполнить поиск по шаблону с самой новой строкой и напечатать самую старую, если она соответствует:

sed -n '
    ## At the beginning read three lines.
    1 { N; N }
    ## Append them to "hold space". In following iterations it will append
    ## only one line.
    H 
    ## Get content of "hold space" to "pattern space" and check if the 
    ## pattern matches. If so, extract content of first line (until a 
    ## newline) and exit.
    g
    /^.*\nsix$/ { 
        s/^\n//
        P
        q 
    }
    ## Remove the old of the three lines saved and append the new one.
    s/^\n[^\n]*//
    h
' infile

Предполагаемый и входной файл (infile) со следующим содержанием:

one
two
three
four
five
six
seven
eight
nine
ten

Будет искать six и как результат будет давать:

four

Вот еще несколько вариантов:

awk '{a[NR]=$0} /pattern/ {f=NR} END {print a[f-2]}' file

Это хранит все строки в массиве a, Когда шаблон найден, хранится номер строки магазина.
По окончании выведите номер строки из файла.
PS может быть медленным с большими файлами


Вот еще один:

awk 'FNR==NR && /pattern/ {f=NR;next} f-2==FNR' file{,}

Это читает файл дважды (file{,} такой же как file file)
В первом раунде он находит шаблон и номер строки магазина в переменной f
Затем во втором раунде он печатает строку два до значения в f

Другие вопросы по тегам