LINUX.ORG.RU

Как заменить/пометить все строки, которые НЕ соответствуют маске?

 


1

1

Например sed 's/^\(сложная маска\)$/#\1/' Пометит знаком # все строки, которые удовлетворяют маске.

А как пометить строки, которые не удовлетворяют маске?

Это нужно, чтобы в тексте(листинге записей с переносами) объединить каждую неполную строку записи, известной структуры, с её продолжением на следующей строке, т.е. вытянуть каждую запись в строку. Перенесенная часть записи может занимать несколько строк. Между разными записями может быть 1 или 2 переноса. Т.е. одинарный либо двойной перенос, как критерий, не годится. Единственный критерий объединения, это начальная структура записи. Она либо обнаруживается, либо нет.

Либо без пометки сразу выполнить требуемое действие.



Последнее исправление: MariaRTI (всего исправлений: 1)

Ответ на: комментарий от Jini

Нашел другой способ: поток|perl -ne 'chomp; print((/^[A-Z][a-z]+ .+, .+$/ && $. != 1 ? «\n» : ($. != 1) ? " " : "") . $_)'

Работает! Он сразу склеивает продолжения записей в одну строку, что и нужно в конце концов.

А этот не работает. Здесь пытаюсь только пометить продолжения записей. Как сделать sed-ом то-же, что и в perl варианте не представляю.

поток|sed '/^[A-Z][a-z]+ .+, .+$/!s,^,#,'

Условия одинаковые.

Проблема решена. Дальнейшее обсуждение интересно только для расширения кругозора и поиска более короткого решения.

MariaRTI
() автор топика
Ответ на: комментарий от MariaRTI

поток|sed '/^[A-Z][a-z]+ .+, .+$/!s,^,#,'

Чтобы у sed в регулярном выражении + работал как в перле, надо добавить опцию -r.

Как сделать sed-ом то-же, что и в perl варианте не представляю.

Например, так:

sed -nr '/^[A-Z][a-z]+ .+, .+$/bp; $bp; H; b; :p x; s,\n, ,g; p'

Но это слишком криптографично. В данном случае perl будет более подходящим инструментом.

Jini ★★
()
Ответ на: комментарий от Jini

Вариант с sed короче и там отсутствуют внутренние кавычки, а значит, при копировании не нужно их экранировать. Может пригодиться!

MariaRTI
() автор топика
Ответ на: комментарий от Jini

Чтобы у sed в регулярном выражении + работал как в перле, надо добавить опцию -r.

Это в какой версии? GNU sed 4.4.0.10 - нет такой опции. Можно экранировать «+» бэкслэшем.

anonymous
()
Ответ на: комментарий от anonymous
> sed --version
sed (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
GNU sed home page: <http://www.gnu.org/software/sed/>.
General help using GNU software: <http://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.

Я ей пользуюсь уже много лет.

Jini ★★
()
Ответ на: комментарий от Jini

И правда, -E работает. Но странно то, что в man не упомянуто. Спасибо за наводку.

anonymous
()
Ответ на: комментарий от Jini

1) Неожиданно обнаружил, что это выражение не эквивалентно перловому, приведенному здесь. Этот вариант иногда удаляет последнюю, вполне нормальную строку, удовлетворяющую условию, а перловый не удаляет.

2) Подскажите пожалуйста, как sed-ом удалить независимо первую и/или последнюю строку, только если они НЕ удовлетворяют этому условию.

Например, это могут быть верхний и нижний колонтитулы или номер страницы или другие пометки на нижнем и верхнем поле страницы.

Вообще не понятно как реализовать условие «не удовлетворяет шаблону» сделать что либо. Перепробовал много вариантов, не получается.

MariaRTI
() автор топика
Ответ на: комментарий от MariaRTI

Вот, например,

удалить первую строку

sed '1d'

удалить строки начинающиеся с V

sed '/^V/d'

но

sed '1/^V/d'

удаляет всё... Почему?

MariaRTI
() автор топика
Ответ на: комментарий от Jini

И ещё касательно обоих вариантов и perl и sed, как ограничить подклеивание продолжений строк только одной строкой? Т.е. принять, что продолжений строк может быть не более одной строки или совсем нет.

Или, что тоже самое, выполнять действия не в цикле, а только один раз для каждого совпадения.

Сейчас оба варианта склеивают в цикле любое количество строк-продолжений после паттерна в одну строку

MariaRTI
() автор топика
Ответ на: комментарий от MariaRTI

1) Неожиданно обнаружил, что это выражение не эквивалентно перловому, приведенному здесь. Этот вариант иногда удаляет последнюю, вполне нормальную строку, удовлетворяющую условию, а перловый не удаляет.

Так лучше?

 sed -nr '/^[A-Z][a-z]+ .+, .+$/bp; H; ${s,.*,,; bp}; b; :p x; s,\n, ,g; /./p; ${x; /./p}'

Однако, мне пришлось поломать голову над этим кодом, и написал я его больше из спортивного интереса. На перле решение пишется сходу и гораздо понятнее:

perl -npe 'chomp; print /^[A-Z][a-z]+ .+, .+$/ ? "\n" : " " if $. > 1; END { print "\n" }'

(немного причёсанный ваш же вариант). Поэтому здесь лучше использовать перл.

2) Подскажите пожалуйста, как sed-ом удалить независимо первую и/или последнюю строку, только если они НЕ удовлетворяют этому условию.

1{/условие/!d}
${/условие/!d}

Оператор {} можно использовать примерно как and: сначала проверяется внешнее условие, а потом внутрь можно вписать другие проверки. В 1{/условие/!d} сначала проверяется номер строки, потом регулярное выражение. Можно и наоборот: /условие/!{1d; $d}.

Jini ★★
()
Ответ на: комментарий от MariaRTI

sed '1/^V/d'

Это некорректное выражение.

Я думаю, на этом этапе пора послать читать маны. Работа со строками, не удовлетворяющими шаблону, описана в разделе Addresses. Пример есть в моём первом комментарии. Возьмите документацию и разберите как работают мои примеры выше если хотите освоить sed.

Jini ★★
()
Последнее исправление: Jini (всего исправлений: 1)
Ответ на: комментарий от Jini

Возьмите документацию и разберите как работают мои примеры выше если хотите освоить sed.

Но конечный результат будет намного лучше, если починить тот генератор, что продуцирует вот эти данные, которые надо такими мучениями редактировать :)

vodz ★★★★★
()
Ответ на: комментарий от vodz

К сожалению, всё что здесь обсуждается не является ошибками генератора. Так напечатано в старых книгах, которые набирались вручную для печати. Там шрифты пляшут вверх вниз, межстрочные интервалы нечёткие.

При распознавании сканов также есть ошибки, но они в этом топике не обсуждаются.

MariaRTI
() автор топика
Ответ на: комментарий от MariaRTI

Лично я не мучаюсь криптоскриптами sed-а, а делаю такие задачи за несколько проходов. То есть один проход - метит, скажем «#», другой - удаляет «\n#», тем самым операция проста и может быть подправлена под разные книги и разные regex в одной последовательно. Я всегда переформатирую книги после скачки с Инета перед чтением :)

vodz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.