Как я могу смешивать шаблоны и числовые диапазоны в sed (или любой подобный инструмент - awk, например)? Я хочу, чтобы это соответствовало определенным строкам в файле и удаляло следующие n строк перед продолжением, и я хочу сделать это как часть конвейера.
Sed или awk: удалить n строк по шаблону
Ответ 1
У меня все получится.
Чтобы удалить 5 строк после шаблона (включая строку с рисунком):
sed -e '/pattern/,+5d' file.txt
Чтобы удалить 5 строк после шаблона (исключая строку с шаблоном):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
Ответ 2
Простые решения awk
:
Предположим, что регулярное выражение для поиска совпадающих строк сохраняется в переменной оболочки $regex
, а количество строк пропускается в $count
.
Если строка соответствия также должна быть пропущена ($count + 1
строки пропущены):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'
Если строка соответствия не должна пропускаться ($count
строки после пропусков совпадения):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'
Объяснение:
-
-v regex="$regex" -v count="$count"
определяет переменныеawk
на основе переменных оболочки с тем же именем. -
$0 ~ regex
соответствует интересующей строке-
{ skip=count; next }
инициализирует подсчет пропусков и переходит к следующей строке, эффективно пропуская соответствующую строку; во втором решенииprint
доnext
гарантирует, что он не будет пропущен. -
--skip >= 0
уменьшает счетчик пропусков и принимает действие, если оно (все еще) >= 0, подразумевая, что строка под рукой должна быть пропущена. -
{ next }
переходит к следующей строке, эффективно пропуская текущую строку
-
-
1
- обычно используемая сокращенная версия для{ print }
; то есть текущая строка просто печатается- Только эта строка не соответствует пропущенным и не пропущенным линиям.
- Причина, по которой
1
эквивалентна{ print }
, заключается в том, что1
интерпретируется как булевский шаблон, который по определению всегда вычисляет значение true, а это означает, что его связанное действие (блок) выполняется безоговорочно. Поскольку в этом случае нет связанных действий,awk
по умолчанию печатает строку.
Ответ 3
Это решение позволяет вам передать "n" в качестве параметра, и он будет читать ваши шаблоны из файла:
awk -v n=5 '
NR == FNR {pattern[$0]; next}
{
for (patt in pattern) {
if ($0 ~ patt) {
print # remove if you want to exclude a matched line
for (i=0; i<n; i++) getline
next
}
}
print
}
' file.with.patterns -
Файл с именем "-" означает stdin для awk, поэтому он подходит для вашего конвейера
Ответ 4
Это может сработать для вас:
cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1
2
3
4
5
9
10
12
13
14
15
21