Ответ 1
У меня все получится.
Чтобы удалить 5 строк после шаблона (включая строку с рисунком):
sed -e '/pattern/,+5d' file.txt
Чтобы удалить 5 строк после шаблона (исключая строку с шаблоном):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
Как я могу смешивать шаблоны и числовые диапазоны в sed (или любой подобный инструмент - awk, например)? Я хочу, чтобы это соответствовало определенным строкам в файле и удаляло следующие n строк перед продолжением, и я хочу сделать это как часть конвейера.
У меня все получится.
Чтобы удалить 5 строк после шаблона (включая строку с рисунком):
sed -e '/pattern/,+5d' file.txt
Чтобы удалить 5 строк после шаблона (исключая строку с шаблоном):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
Простые решения 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
по умолчанию печатает строку.Это решение позволяет вам передать "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, поэтому он подходит для вашего конвейера
Это может сработать для вас:
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