Вопрос или проблема
Входной файл:
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
могут вернуть ненулевой статус даже при наличии ошибок, или в случае когда файл не удается сохранить.
Шаги решения
- Удаление завершающих слешей: Нам нужно будет использовать команду подстановки, чтобы удалить завершающие слеши (
\
) с конца каждой строки. - Удаление последовательных пустых строк: Необходимо будет использовать глобальную команду
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
.