Как преобразовать escape-последовательности в текст, сохраняя формат отображения?

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

У меня есть текстовый файл, который содержит (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 с пустым config файлом (/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

Заключение

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

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

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