Удаление более чем двух последовательных пустых строк с помощью ed

Вопрос или проблема

Входной файл:

1 line1\
2 line2\
3 line3\
4 \
5 line4\
6 \
7 \
8 line5\

Желаемый вывод:

1 line1
2 line2
3 line3
4
5 line4
6
7 line5

Возможно ли это с помощью POSIX ed?

Удалить завершающие обратные слеши легко, но как я могу также обработать последовательные обратные слеши как в ожидаемом выводе?

С помощью sed вы могли бы сделать:

sed 's/\\$//;/./,/^$/!d'

Одна из основных проблем с ed (помимо его синтаксиса из другой эпохи) — управление ошибками в скрипте.

По сути, нужно думать об этом так, что ed возвращает успешный результат, если он успешно отредактировал файл. Но чтобы редактирование было успешным, адрес каждой команды должен быть действительным, а каждая команда должна быть успешной (например, для команды s это означает, что должно быть выполнено хотя бы одно замещение).

Так что, если вы хотите проверить, что редактирование было успешным в этом случае, это может быть непросто.

Чтобы развить решение @Sukminder и попытаться покрыть крайние случаи, можно написать:

printf '%s\n' a a . 'g/\\$/s///' ',s/^/a/' 'g/^a$/+1,/./s/^a$//' \
  'v/./d' 'g/^a/s///' '$d' w | ed -s the-file

Команда g не сработает, если файл был пустым (поскольку диапазон адресов по умолчанию (1,$) будет недействительным, поэтому сначала нужно добавить строку в конец файла (с помощью команды a). ,s/\\$// не сработает, если не будет строк, заканчивающихся на \, поэтому мы должны выполнять это только в случае наличия таких строк (g/\\$/s///).

Здесь, вместо того чтобы вставить “xx”, предполагая, что это не встретится в вводе, мы добавляем “a” к каждой строке и заменяем строки, которые необходимо удалить, на пустую строку, которую мы затем удаляем.

Надеюсь, что этот скрипт ed будет возвращать ненулевой код завершения только в случае неудачи при записи файла (при сбое команды w). К сожалению, я видел реализации ed, которые возвращали успешный статус при неудаче записи файла, когда файловая система была полной.

На мой взгляд, ed лучше избегать. В наши дни использование perl -pi.back является таким же портативным и более надежным.

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

# Добавить XX к строкам, которые должны быть удалены
g/^$/+1s/^$/XX/
# Удалить их
g/XX/d

Но это не очень красиво.

Ответ или решение

С удалением более чем двух последовательных пустых строк в текстовом файле с использованием программы ed можно столкнуться с определенными трудностями. Программа ed, хотя и является мощным инструментом для редактирования текстовых файлов, подразумевает более сложный подход в сравнении с современными утилитами, такими как sed или perl.

Постановка задачи

Имеется текстовый файл с данными:

1 line1\
2 line2\
3 line3\
4 \
5 line4\
6 \
7 \
8 line5\

Необходимо преобразовать его, удалив завершающие обратные слеши и убрав последовательные пустые строки, чтобы получить следующий результат:

1 line1
2 line2
3 line3
4
5 line4
6
7 line5

Возможность выполнения с помощью ed

В ed можно решить задачу, однако потребуется использовать несколько шагов, чтобы учесть особенности работы этой утилиты. В ed команда g (глобальная команда) может завершиться с ошибкой, если в файле отсутствуют подходящие строки. Важно понимать, что команды ed могут вернуть ненулевой статус даже при наличии ошибок, или в случае когда файл не удается сохранить.

Шаги решения

  1. Удаление завершающих слешей: Нам нужно будет использовать команду подстановки, чтобы удалить завершающие слеши (\) с конца каждой строки.
  2. Удаление последовательных пустых строк: Необходимо будет использовать глобальную команду g для поиска и удаления пустых строк, но с учетом того, что может быть несколько подряд идущих пустых строк, это усложняет задачу.

Пример команды ed

Пример скрипта ed для выполнения вышеуказанных задач может выглядеть так:

printf '%s\n' a a . 'g/\\$/s/\\$//' 'g/^$/s/^$/XX/' 'g/^XX/d' 'v/./d' 'g/^a/s///' '$d' w | ed -s the-file

Объяснение команд:

  • printf '%s\n' a a .: добавляет временную строку (содержащую "a"), чтобы избежать ошибок при обработке пустого файла.
  • g/\\$/s/\\$//: ищет строки, заканчивающиеся на \, и удаляет этот символ.
  • g/^$/s/^$/XX/: помечает пустые строки временным маркером "XX".
  • g/^XX/d: удаляет маркеры "XX", тем самым удаляя пустые строки.
  • v/./d: удаляет все но не пустые строки.
  • g/^a/s///: восстанавливает строки без маркера "a" (восстанавливает оригинальные строки).
  • $d: удаляет последнюю временную строку, добавленную в начале.
  • w: сохраняет файл.

Заключение

Несмотря на возможность использования ed для данной задачи, следует отметить сложность и вероятность возникновения ошибок при работе с этой утилитой. В современных условиях рекомендуется рассмотреть использование более удобных и надежных средств, таких как perl или sed, которые предлагают более мощные и гибкие функции для редактирования текста. Это значительно упрощает процесс и минимизирует риск ошибок из-за особенностей работы ed.

Оцените материал
Добавить комментарий

Капча загружается...