Получить номер строки первой строки, соответствующей второму шаблону - PullRequest
0 голосов
/ 14 июня 2019

Можно ли использовать awk или sed, чтобы получить номер строки, такой, что это первая строка, соответствующая регулярному выражению, после другой строки, соответствующей другому регулярному выражению?

Другими словами:

  1. Найти строку l1, соответствующую регулярному выражению r1. l1 - первая строка, совпадающая с r1.
  2. Найдите строку l2 ниже l1. l2 соответствует регулярному выражению r2. l2 - первая строка, совпадающая с r2, игнорируя строки l1 и выше.

Уточнение: Под совпадением я подразумеваю частичное совпадение для наиболее общего решения. Частичное совпадение, конечно, можно превратить в совпадение с полным словом с помощью \<...\> или совпадение с полной строкой с помощью ^...$.

Пример ввода:

- - '787928'
  - stuff
- - '810790'
  - more stuff
- - '787927'
  - yet more stuff
- - '828055'
  - some more stuff
- - '828472'
  - some other stuff

Если r1 равно ^-.*787927.* и r2 равно ^-, я ожидаю, что на выходе будет 7, то есть номер строки, которая говорит - - '828055'.

Ответы [ 3 ]

3 голосов
/ 14 июня 2019

Для входного файла, который выглядит следующим образом:

 1  pat2
 2  x
 3  pat1
 4  x
 5  pat2
 6  x
 7  pat1
 8  x
 9  pat2

Вы можете использовать sed следующим образом:

$ sed -n '/pat1/,${/pat2/{=;q;};}' infile
5

, который работает так:

sed -n '       # suppress output with -n
/pat1/,$ {     # for all lines from the first occurrence of "pat1" on...
    /pat2/ {   # if the line matches "pat2"
        =      # print line number
        q      # quit
    }
}' infile

Вышеприведенное не выполняется, если первое вхождение pat1 находится на той же строке, что и pat2:

 1  pat2
 2  x
 3  pat1 pat2
 4  x
 5  pat2
 6  x
 7  pat1
 8  x
 9  pat2

напечатает 3. С помощью GNU sed мы можем использовать это вместо:

$ sed -n '0,/pat1/!{/pat2/{=;q;};}' infile
5
sed -n '     # suppress output
0,/pat1/! {  # for all lines after the first occurrence of "pat1"
    /pat2/ { # if the line matches "pat2"
        =    # print line number
        q    # quit
    }
}' infile

Адрес 0 является расширением GNU; использование 1 вместо этого прервется, если pat1 будет в первой строке.

3 голосов
/ 14 июня 2019

Пример ввода:

world
zekfzlefkzl
fezekzevnkzjnz
hello
zeniznejkglz
world
eznkflznfkel
hello
zenilzligeegz
world

Команда:

pat1="hello"; pat2="world";
awk -v pat1=$pat1 -v pat2=$pat2 '$0 ~ pat1{pat1_match = 1}($0 ~ pat2)&&pat1_match{print NR; exit}' <input>

Выход:

6
0 голосов
/ 15 июня 2019

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

sed -n '/^-.*787927.*/{:a;n;/^-/!ba;=;q}' file

При обнаружении строки, которая начинается -.*787927.*, запустите цикл, который заменяет текущую строку следующей, до тех пор, пока не начнется строка -, где после печати выведите номер строки и выйдите из нее.

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