sed: удалить предыдущую строку - PullRequest
4 голосов
/ 10 марта 2012

Мне нужно удалить пустую строку перед совпадением.

Итак, с учетом файла:

random text
more random text






#matchee

Мне нужно сопоставить шаблон / # matchee /, а затем удалить пустую строку перед ним.

Вот что я попробовал - безуспешно:

sed '/^[ \t]*$/{N;/#matchee.*$/{D;}}' file.txt

Моя логика:

  • Если пустая строка; добавить следующую строку к шаблону, получая / пустую строку \ n ... и т.д. /
  • Если пространство шаблона содержит / # matchee /, Удалить до новой строки, получая / # matchee /

В основном / matchee / - это константа, которую нужно поддерживать, и мне нужно удалить лишнюю пустая строка из каждой записи в файле записей, разделенных /#matchee/.

Это никак не влияет. Я RTFM-ing и D должен удалить шаблон пробел до новой строки. Так как N добавляет символ новой строки плюс следующую строку - это должно дать желаемые результаты .... увы .... нет и снова нет. Это потому, что совпадение по сути ничего не содержит (пустая строка)?

Ответы [ 2 ]

5 голосов
/ 10 марта 2012

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

  • захватывает строку L1 и добавляет ее в пространство шаблона
  • , если L1 не является пустым, напечатайте его;но если пусто , то:
    • возьмите другую строку, L2 и добавьте ее в пространство шаблона
    • , если L2 содержит #matchee, отбрасывает L1 из пространства шаблона
    • печатает пространство шаблона, состоящее из L1 и L2 или просто из L2

Вы заметите, что L2 всегда печатается, даже если оно пустое и сопровождаетсястрока, содержащая #matchee.Он защищен тем, что сразу следует нечетное количество пустых строк.

Отредактировано, чтобы добавить: Чтобы исправить вышеописанную проблему, вы можете добавить внутренний цикл, используя *Команда 1044 * для создания метки и команда b для ее «ветвления» (переход).Это:

sed '/^[ \t]*$/{: a;N;/#matchee/!P;D;/^[ \t]*$/b a}' file.txt

представляет собой цикл следующего:

  • захватывает строку L1 и добавляет ее в пространство шаблона
  • если L1 не пусто, распечатайте его;но если оно пусто , то:
    • создать метку a ← это неактивно, просто место для goto
    • , чтобы взять другую строку, L2 и добавьте его в пространство шаблона
    • , если L2 не не содержит #matchee, печать L1
    • сброс L1 из пространства шаблона (независимо от того, печатали мы его или нет)
    • теперь мы можем думать о L2 как L1 ;это единственное в пространстве шаблона
    • , если переименованный L1 пуст, goto a
2 голосов
/ 10 марта 2012

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

sed '$!N;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt

чтобы понять, как это работает, запустите:

sed '$!N;l;s/^\s*\n\(#matchee.*\)/\1/;P;D' file.txt

N.B. P печатает до первой новой строки, D удаляет до первой новой строки и начинает новый цикл без чтения в другой записи, если нет новой строки, в этом случае он ведет себя как d, читает в строке и начинает следующий цикл.

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