Вопрос или проблема
У меня есть текстовый файл, который содержит (ANSI ?) управляющие последовательности:
Когда я использую cat
для чтения файла, я получаю отформатированный вывод:
Как мне сохранить / перенаправить вывод текстового файла в новый файл, чтобы управляющие коды были удалены, но форматирование сохранилось?
Другими словами, я хочу конвертировать / экспортировать содержимое файла в новый файл, сохранив предполагаемый формат отображения (например, как это было бы при использовании less -r <file>
).
Мне нужен автоматизированный способ сделать это, чтобы результат можно было зарегистрировать и отправить как уведомление по электронной почте.
Вот base64 вывод файла из приведенных выше скриншотов (используйте base64 -d
для декодирования):
G1tIG1syShtbMTsxSA0KG1s0OzRIICAgICAgICAgICAgICAgICAgICAgICAgICBDT05GSURFTlRJ
QUwgSU5GT1JNQVRJT04bW0sbWzU7NEgbW0sbWzY7NEgbW0sbWzc7NEhUaGlzIHdvcmsgY29udGFp
bnMgdmFsdWFibGUsIGNvbmZpZGVudGlhbCwgYW5kIHByb3ByaWV0YXJ5IGluZm9ybWF0aW9uLhtb
SxtbODs0SERpc2Nsb3N1cmUsIHVzZSwgb3IgcmVwcm9kdWN0aW9uIGlzIGdvdmVybmVkIGJ5IHlv
dXIgTGljZW5zZSBBZ3JlZW1lbnQuG1tLG1sxMDs0SBtbSxtbMTE7NEhUaGlzIHVucHVibGlzaGVk
IHdvcmsgaXMgcHJvdGVjdGVkIGJ5IHRoZSBsYXdzIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGFuZBtb
SxtbMTI7NEhvdGhlciBDb3VudHJpZXMuICBUaGUgd29yayB3YXMgY3JlYXRlZCBpbiAxOTg4IGFu
ZCByZXZpc2VkIGluIDE5OTQuICAbW0sbWzEzOzRISWYgcHVibGljYXRpb24gb2NjdXJzLCB0aGUg
Zm9sbG93aW5nIG5vdGljZSBzaGFsbCBhcHBseTobW0sbWzE0OzRIG1tLG1sxNTs0SBtbSxtbMTY7
NEggICBDb3B5cmlnaHQgMTk4OCwxOTk0LiBBbGwgcmlnaHRzIHJlc2VydmVkLhtbSxtbMTc7NEgb
W0sbWzE4OzRIG1tLG1sxOTs0SFRoaXMgQ29peXJpZ2h0IG5vdGljZSBhbmQgb3RoZXIgY29weXJp
Z2h0IG5vdGljZXMgaW5jbHVkZWQgaW4gdGhlIG1hY2hpbmUbW0sbWzIwOzRIcmVhZGFibGUgY29w
aWVzIG11c3QgYmUgcmVwcm9kdWNlZCBvbiBhbGwgYXV0aG9yaXplZCBjb3BpZXMuG1tLG1syMTs0
SBtbSxtbMjI7NEhUaGlzIGlzIGEgcmVnaXN0ZXJlZCB0cmFkZW1hcmsuG1tLDQo=
Лучший способ – использовать эмулятор терминала для интерпретации этих последовательностей и сказать ему, чтобы он вывел текстовое содержимое в результате.
screen
– один из таких эмуляторов терминала, с которым вы можете легко взаимодействовать в скрипте. Вы можете сделать следующее:
INPUT=file.txt OUTPUT=output.txt screen -Dmc /dev/null sh -c '
screen -X scrollback 100000
cat < "$INPUT"
screen -X hardcopy -h "$OUTPUT"'
Это запускает новую (-m
) D
етаченную сессию screen
с пустым c
onfig файлом (/dev/null
). В ней мы выполняем встроенный sh
скрипт в окне экрана, увеличиваем размер прокрутки (хотя вывод поместится на одном экране), помещаем входной файл в окно экрана, а затем вызываем hardcopy -h
, чтобы выгрузить содержимое экрана, включая прокрутку, в выходной файл.
Файл содержит несколько управляющих последовательностей (символьная последовательность ^[
является управляющим символом):
-
^[[2J
, очищает экран. -
^[[H
, перемещает курсор к верхней части экрана. -
^[[x;yH
, перемещает курсор в позицию(x,y)
.Это означает, что файл в основном использует абсолютное позиционирование текста на экране.
-
^[[K
очищает до конца строки.
Файл также содержит пару возвратов каретки, которые мы, возможно, захотим удалить.
Мы можем выбрать удалить большинство из них, но заменить последовательности “перемещение на (x,y)
” на одну новую строку для простоты. К счастью, каждое такое позиционирование просто опускает курсор на строку вниз и отступает на четыре пробела (нет “вне последовательности” строк текста).
sed -e $'s/\e\\[2J//g' \
-e $'s/\e\\[H//g' \
-e $'s/\e\\[[[:digit:]]*;[[:digit:]]*H/@ /g' -e 'y/@/\n/' \
-e $'s/\e\\[K//g' \
-e $'s/\r//g' file
Замены здесь выполняются с использованием C-строк в оболочке ($'...'
, поддерживается, например, в bash
и zsh
) для кодирования управляющих символов.
Каждая последовательность ^[[x;yH
заменяется на новую строку и четыре пробела отступа в два этапа; сначала заменяем их на @
(@
– это любой символ, который отсутствует в данных), а затем заменяем каждый @
на новую строку с помощью y///
. Это связано с тем, что s///
не может вставлять новые строки (хотя GNU sed
может).
Мы также можем выбрать использовать вывод команды cat -v
для работы с данными. Это делает некоторые управляющие символы видимыми в однозначной форме.
$ cat -v file
^[[H^[[2J^[[1;1H^M
^[[4;4H CONFIDENTIAL INFORMATION^[[K^[[5;4H^[[K^[[6;4H^[[K^[[7;4HThis work contains valuable, confidential, and proprietary information.^[[K^[[8;4HDisclosure, use, or reproduction is governed by your License Agreement.^[[K^[[10;4H^[[K^[[11;4HThis unpublished work is protected by the laws of the United States and^[[K^[[12;4Hother Countries. The work was created in 1988 and revised in 1994. ^[[K^[[13;4HIf publication occurs, the following notice shall apply:^[[K^[[14;4H^[[K^[[15;4H^[[K^[[16;4H Copyright 1988,1994. All rights reserved.^[[K^[[17;4H^[[K^[[18;4H^[[K^[[19;4HThis Copyright notice and other copyright notices included in the machine^[[K^[[20;4Hreadable copies must be reproduced on all authorized copies.^[[K^[[21;4H^[[K^[[22;4HThis is a registered trademark.^[[K^M
Здесь мы можем использовать следующую команду sed
:
cat -v file |
sed -e 's/\^\[\[2J//g' \
-e 's/\^\[\[H//g' \
-e 's/\^\[\[[[:digit:]]*;[[:digit:]]*H/@ /g' -e 'y/@/\n/' \
-e 's/\^\[\[K//g' \
-e 's/\^M//g'
Обратите внимание, что опция -v
для cat
не является стандартной, но вывод реализации cat
, которые поддерживают ее, кажется, последовательный.
На некоторых системах утилита vis
может быть использована вместо cat -v
, но она генерирует другие видимые представления управляющих символов.
Простой способ – использовать команду truncate с опцией delete. \033 представляет собой управляющий символ.
cat your_filename|tr -d \033 > save_filename
Используйте следующую команду, чтобы удалить все управляющие символы:
cat your_filename|tr -d [:cntrl:] > save_filename
Надеюсь, это поможет.
Ответ или решение
Чтобы преобразовать управляющие последовательности (экранированные последовательности) в текст, сохраняя при этом форматирование вывода, в Linux можно воспользоваться рядом инструментов, таких как sed
, tr
, и терминальными эмуляторами, например, screen
. Здесь приведены несколько подходов для решения данной задачи.
1. Использование sed
С помощью команды sed
можно удалить управляющие последовательности и сохранить соответствующее текстовое форматирование. Пример команды:
sed -e $'s/\e\\[2J//g' \
-e $'s/\e\\[H//g' \
-e $'s/\e\\[[[:digit:]]*;[[:digit:]]*H/@ /g' \
-e 'y/@/\n/' \
-e $'s/\e\\[K//g' \
-e 's/\r//g' input_file.txt > output_file.txt
Объяснение ключевых замен:
s/\e\\[2J//g
: удаляет команду очистки экрана.s/\e\\[H//g
: удаляет команду перемещения курсора в верхнюю часть экрана.s/\e\\[[[:digit:]]*;[[:digit:]]*H/@ /g
: заменяет команды перемещения курсора на символ@
с четырьмя пробелами.y/@/\n/
: заменяет символ@
на перенос строки.s/\e\\[K//g
: удаляет команду очистки строки.s/\r//g
: удаляет символы возврата каретки.
2. Использование tr
Можно использовать tr
для быстрого удаления всех управляющих символов. Например:
cat input_file.txt | tr -d '\033' > output_file.txt
Или для удаления всех непечатаемых символов можно использовать:
cat input_file.txt | tr -d [:cntrl:] > output_file.txt
3. Использование screen
Если нужно сохранить текст с учетом позиции курсора, можно использовать терминальный эмулятор screen
. Вот пример скрипта:
INPUT=file.txt
OUTPUT=output.txt
screen -Dmc /dev/null sh -c '
screen -X scrollback 100000
cat < "$INPUT"
screen -X hardcopy -h "$OUTPUT"'
Этот код запускает новую сессию screen
, увеличивает размер буфера прокрутки, выводит содержимое файла в окно screen
, а затем сохраняет содержимое экрана в файл.
4. Альтернативный метод с помощью cat -v
Можно сначала сделать управляемый вывод с помощью cat -v
, чтобы сделать невидимые символы видимыми:
cat -v input_file.txt | sed -e 's/\^\[\[2J//g' \
-e 's/\^\[\[H//g' \
-e 's/\^\[\[[[:digit:]]*;[[:digit:]]*H/@ /g' \
-e 'y/@/\n/' \
-e 's/\^\[\[K//g' \
-e 's/\^M//g' > output_file.txt
Заключение
Каждый из этих методов может использоваться для преобразования текстового файла с управляющими последовательностями в чистый текст, сохраняя при этом необходимый формат. Выбор конкретного метода зависит от того, какие именно требования у вас есть к форматированию и простоте выполнения.