sed или awk: удалить n строк, следующих за шаблоном - PullRequest
88 голосов
/ 09 декабря 2010

Как бы я смешал шаблоны и числовые диапазоны в sed (или любом другом подобном инструменте - например, awk)?Я хочу сопоставить определенные строки в файле и удалить следующие n строк перед продолжением, и я хочу сделать это как часть конвейера.

Ответы [ 6 ]

155 голосов
/ 09 декабря 2010

Я попробую это сделать.

Чтобы удалить 5 строк после шаблона (включая строку с шаблоном):

sed -e '/pattern/,+5d' file.txt

Чтобы удалить 5 строк после шаблона(исключая строку с рисунком):

sed -e '/pattern/{n;N;N;N;N;d}' file.txt
5 голосов
/ 20 мая 2015

Простые 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 переменные на основе shell переменных с тем же именем.
  • $0 ~ regex соответствует линии интереса
    • { skip=count; next } инициализирует счетчик пропусков и переходит к следующей строке, эффективно пропуская совпадающую строку; во втором решении print перед next гарантирует, что оно не пропущено.
    • --skip >= 0 уменьшает число пропусков и предпринимает действия, если оно (все еще)> = 0, подразумевая, что текущая строка должна быть пропущена.
    • { next } переходит к следующей строке, фактически пропуская текущую строку
  • 1 является обычно используемым сокращением для { print }; то есть текущая строка просто печатается
    • Только несоответствующие и пропущенные строки достигают этой команды.
    • Причина, по которой 1 эквивалентна { print }, заключается в том, что 1 интерпретируется как логический шаблон, который по определению всегда оценивается как true, что означает, что его соответствующее действие (блок) выполняется безоговорочно. Так как в этом случае нет связанного действия, awk по умолчанию печатает строку.
2 голосов
/ 31 декабря 2018

Использование Perl

$ cat delete_5lines.txt
1
2
3
4
5 hello
6
7
8
9
10
11 hai
$ perl -ne ' BEGIN{$y=1} $y=$.  if /hello/ ; print if $y==1 or $.-$y > 5 ' delete_5lines.txt
1
2
3
4
11 hai
$
2 голосов
/ 20 января 2012

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

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
2 голосов
/ 09 декабря 2010

Это решение позволяет вам передавать "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, поэтому он подходит для вашего конвейера

1 голос
/ 30 декабря 2018

Без расширений GNU (например, в macOS):

Для удаления 5 строк после шаблона (включая строку с шаблоном)

 sed -e '/pattern/{N;N;N;N;d;}'

Добавить -i '' для редактирования на месте.

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