grep для возврата N-й и M-й строк до и после матча

Я знаю, что с помощью grep я могу использовать поля -A и -B, чтобы извлечь предыдущую и следующую строки из совпадения.

Однако они вытягивают все строки между совпадениями, основываясь на том, сколько строк указано.

grep -r -i -B 5 -A 5 "match" 

Я хотел бы получить только 5 th строку перед совпадением и 5 th строку после совпадения в дополнение к сопоставленной строке, а не получить линии между.

Есть ли способ сделать это с grep?

11
задан 10 May 2018 в 22:25

6 ответов

Инструмент, который Вы хотите использовать, называют, отсеивают. Это - в основном grep на стероидах. Grep параллельно. Отсейте имеет огромное количество опций сделать точно, что Вы хотите - конкретно возвратить конкретную строку относительно соответствия (соответствий), которое не может сопровождаться/, которому предшествует некоторый текст.

Это поражает меня, которые отсеивают, не основная гну, как это было записано на языке движения, но установках на Linux очень хорошо. IT ищет в параллели с помощью всех CPU огромные количества текста, где grep просто занимает недели, чтобы сделать то же.

Отсейте веб-сайт - посмотрите примеры

1
ответ дан 23 November 2019 в 03:52

Если:

cat file
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o

Затем:

awk '
    {line[NR] = $0} 
    /match/ {matched[NR]} 
    END {
        for (nr in matched)
            for (n=nr-5; n<=nr+5; n+=5) 
                print line[n]
    }
' file
a
f match
k
d
i match
n
12
ответ дан 23 November 2019 в 03:52

Это - в основном решение Glenn, но реализованный с Bash, Grep и sed.

grep -n match file |
    while IFS=: read nr _; do
        sed -ns "$((nr-5))p; $((nr))p; $((nr+5))p" file
    done

Обратите внимание, что номера строки, меньше чем 1 совершит sed ошибку и номера строки, больше, чем количество строк в файле, заставят его ничего не распечатать.

Это - просто абсолютный минимум. Заставить его работать рекурсивно и обработать вышеупомянутые случаи номера строки взяло бы некоторое выполнение.

6
ответ дан 23 November 2019 в 03:52

Это не может быть, покончили только grep. Если edопция:

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  

В сценарии в основном говорится: для каждого соответствия соответствия//, распечатайте строку 5 строк перед этим, затем 5 строк после этого, затем 5 строк после этого.

6
ответ дан 23 November 2019 в 03:52
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile

Здесь мы используем awk's system(command) функционируйте для вызова внешним sed управляйте для печати строк, которым awk соответствовал шаблону match с 5-ми строками прежде и после соответствия.

Синтаксис легок, просто необходимо поместить саму внешнюю команду в двойной кавычке, а также ее переключателях и выйти из вещей, Вы хотите точно передачу в команду, все остальное связанное с awk самостоятельно опции должны быть за пределами кавычек. Так ниже sed:

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME

переведите в:

sed -n "NR-5p; NRp; NR+5p" FILENAME

NR номер строки, который соответствовал шаблону match и FILENAME текущего проходящего мимо имени файла обработки awk.

5
ответ дан 23 November 2019 в 03:52

использование текстового файла @glenn в качестве примера и использование жемчуга вместо awk:

$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex

даст те же результаты, но выполнение быстрее:

a
f match
k
d
i match
n
2
ответ дан 23 November 2019 в 03:52

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

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