Я знаю, что с помощью grep я могу использовать поля -A
и -B
, чтобы извлечь предыдущую и следующую строки из совпадения.
Однако они вытягивают все строки между совпадениями, основываясь на том, сколько строк указано.
grep -r -i -B 5 -A 5 "match"
Я хотел бы получить только 5 th sup> строку перед совпадением и 5 th sup> строку после совпадения в дополнение к сопоставленной строке, а не получить линии между.
Есть ли способ сделать это с grep
?
Инструмент, который Вы хотите использовать, называют, отсеивают. Это - в основном grep на стероидах. Grep параллельно. Отсейте имеет огромное количество опций сделать точно, что Вы хотите - конкретно возвратить конкретную строку относительно соответствия (соответствий), которое не может сопровождаться/, которому предшествует некоторый текст.
Это поражает меня, которые отсеивают, не основная гну, как это было записано на языке движения, но установках на Linux очень хорошо. IT ищет в параллели с помощью всех CPU огромные количества текста, где grep просто занимает недели, чтобы сделать то же.
Если:
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
Это - в основном решение 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 ошибку и номера строки, больше, чем количество строк в файле, заставят его ничего не распечатать.
Это - просто абсолютный минимум. Заставить его работать рекурсивно и обработать вышеупомянутые случаи номера строки взяло бы некоторое выполнение.
Это не может быть, покончили только grep
. Если ed
опция:
ed -s file << 'EOF'
g/match/-5p\
+5p\
+5p
EOF
В сценарии в основном говорится: для каждого соответствия соответствия//, распечатайте строку 5 строк перед этим, затем 5 строк после этого, затем 5 строк после этого.
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
.
использование текстового файла @glenn в качестве примера и использование жемчуга вместо awk:
$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex
даст те же результаты, но выполнение быстрее:
a
f match
k
d
i match
n