Видалення ANSI-кольорів з текстового потоку


73

Вивчення результатів з

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";'

у текстовому редакторі (наприклад, vi) відображається наступне:

^[[37mABC
^[[0m

Як можна видалити коди кольорів ANSI з вихідного файлу? Я вважаю, що найкращим способом було б передавати вихід через своєрідний редактор потоків.

Наступне не працює

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | perl -pe 's/\^\[\[37m//g' | perl -pe 's/\^\[\[0m//g'

Це не відповідь на запитання, але ви також можете передавати висновок moreабо less -Rякий може інтерпретувати коди ескалації як колір замість текстового редактора.
тердон

Відповіді:


98

Символи ^[[37mта ^[[0mє частиною послідовностей аварійних передач ANSI (коди CSI) . Дивіться також ці специфікації .

Використання GNU sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(або \x1B) є спеціальним символом втечі
    ( sedне підтримує альтернативи \eта \033)
  • \[ є другим символом послідовності втечі
  • [0-9;]* - значення кольору (s)
  • m є останнім символом послідовності втечі

У macOS sedкоманда за замовчуванням не підтримує спеціальні символи, як, наприклад \e, вказано slm та steamer25 у коментарях. Натомість використовуйте, gsedщо ви можете встановити за допомогою brew install gnu-sed.

Приклад з командним рядком OP :   (OP означає оригінальний плакат)

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | 
      sed 's/\x1b\[[0-9;]*m//g'

Том Хейл пропонує видалити всі інші послідовності евакуації, використовуючи [a-zA-Z]замість лише букву, mспецифічну для графічного режиму (кольору) послідовності виходу. Але [a-zA-Z]може бути занадто широким і може видалити занадто багато. Міхал Faleński і Miguel Mota пропонують видалити тільки деякі керуючі послідовності , використовуючи [mGKH]і [mGKF]відповідно. Бріттон Керін вказує, що Kнеобхідно також використовувати mдля видалення кольорів gccпомилки / попередження (не забудьте переспрямувати gcc 2>&1 | sed...).

sed 's/\x1b\[[0-9;]*m//g'           # Remove color sequences only
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'    # Remove all escape sequences
sed 's/\x1b\[[0-9;]*[mGKH]//g'      # Remove color and move sequences
sed 's/\x1b\[[0-9;]*[mGKF]//g'      # Remove color and move sequences
Last escape
sequence
character   Purpose
---------   -------------------------------
m           Graphics Rendition Mode (including Color)
G           Horizontal cursor move
K           Horizontal deletion
H           New cursor position
F           Move cursor to previous n lines

Використання perl

Версія, sedвстановлена ​​в деяких операційних системах, може бути обмежена (наприклад, macOS). Команда perlмає перевагу в тому, що в цілому простіше встановити / оновити на більшій кількості операційних систем. Адам Кац пропонує використовувати \e(те саме, що \x1b) в PCRE .

Виберіть свій регулярний вираз залежно від того, скільки команд ви хочете відфільтрувати:

perl -pe 's/\e\[[0-9;]*m//g'          # Remove colors only
perl -pe 's/\e\[[0-9;]*[mG]//g'
perl -pe 's/\e\[[0-9;]*[mGKH]//g'
perl -pe 's/\e\[[0-9;]*[a-zA-Z]//g'
perl -pe 's/\e\[[0-9;]*m(?:\e\[K)?//g' # Adam Katz's trick

Приклад з командним рядком OP:

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' \
      | perl -pe 's/\e\[[0-9;]*m//g'

Використання

Як зазначається у коментарі Стюарта Кардалла , цей sedкомандний рядок використовується проектом Ultimate Nginx Bad Bot (1000 зірок) для очищення звіту електронної пошти ;-)


2
Дякую за sedкоманду та пояснення. :)
Редсандро

2
Деякі кольорові коди (наприклад, термінал Linux) містять префікс, наприклад, 1;31mтак що краще додайте ;до свого регулярного виразу: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'інакше вони не знімуться.
Редсандро

1
це чудово, використовуючи його в github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/… для очищення звіту електронної пошти.
Стюарт Кардалл

2
Майте на увазі, що версія OSX sedне працювала за наведеним прикладом, gsedпроте версія.
slm

2
Більше контексту для коментаря slm щодо OSX sed: він не підтримує керуючих символів, таких як \ x1b. Наприклад, stackoverflow.com/a/14881851/93345 . Ви можете отримати команду gsed через brew install gnu-sed.
пароплав25


10

Що відображається як ^[це НЕ ^ і [; це ESCсимвол ASCII , породжений Escабо Ctrl[( ^позначення означає ключ Ctrl).

ESCдорівнює 0x1B в шістнадцятковій або 033 вісімковій частині, тому вам доведеться використовувати \x1Bабо \033у своїх регулярних виразах:

perl -pe 's/\033\[37m//g; s/\033[0m//g'

perl -pe 's/\033\[\d*(;\d*)*m//g'

6

Якщо ви віддаєте перевагу щось просте, ви можете використовувати модуль strip-ansi ( потрібен Node.js ):

$ npm install --global strip-ansi-cli

Потім використовуйте його так:

$ strip-ansi < colors.o

Або просто передайте рядок:

$ strip-ansi '^[[37mABC^[[0m'

Це марне використання cat( UUOC ) - це має бути можливо зробити strip-ansi colors.oабо принаймні strip-ansi < colors.o.
Скотт

1
@Scott Sure, ви також можете це зробити strip-ansi < colors.o, але з досвіду люди більше знайомі з трубопроводами. Я оновив відповідь.
Сіндре Сорхус

хороше просте рішення
Penghe Geng


2

Питання "відповів" не спрацювало для мене, тому я створив цей регулярний вимір замість цього, щоб видалити послідовності евакуації, створені модулем perl Term :: ANSIColor.

cat colors.o | perl -pe 's/\x1b\[[^m]+m//g;

Регекс Grawity повинен добре працювати, але використання + 's, здається, теж добре.


4
(1) Що ви маєте на увазі під The "answered" question? Ви маєте на увазі прийняту відповідь? (2) Ця команда не працює - вона навіть не виконується - тому що вона має незрівнянну (незбалансовану) цитату. (3) Це марне використання cat( UUOC ) - це слід зробити . (4) Хто коли-небудь говорив про коди, що знаходяться у файлі? perl -pe command colors.o.o
Скотт

2

Я вважаю, що це авторитетне видалення всіх послідовностей втечі ANSI :

perl -pe '
  s/\e\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]//g;
  s/\e[PX^_].*?\e\\//g;
  s/\e\][^\a]*(?:\a|\e\\)//g;
  s/\e[\[\]A-Z\\^_@]//g;'

(Зверніть увагу , що PERL, як і багато інших мов (але не СЕД), приймає в \eякості екрануючого символу Esc, \x1bабо з \033допомогою коду, показаного в терміналах , як ^[. Я використовую його тут , бо здається більш зрозумілим.)

Ця команда perl, яку ви можете запустити всі в одному рядку, якщо хочете, має чотири заміни:

Перша йде після послідовностей CSI (послідовності відхідного коду, що починаються з "Введення послідовності управління" Esc[, що охоплює набагато більше, ніж послідовності Select Graphic Rendition, що складають кольорові коди та інші текстові прикраси).

Друга заміна видаляє решта послідовностей, які включають символи, що закінчуються, і закінчуються ST (String Terminator, Esc\). Третя заміна це те ж саме , але також дозволяє команд операційної системи послідовності , щоб закінчити з BEL ( \x07, \007часто \a).

Четверта заміна видаляє залишилися втечі.

Також розгляньте можливість видалення інших символів ASCII нульової ширини, таких як BEL та інших більш неясних контрольних символів C0 та C1 . Я використовував s/[\x00-\x1f\x7f-\x9f\xad]+//g, що включає також Видалити та м'який дефіс . Це виключає більш кодовані символи нульової ширини Unicode, але я вважаю, що це вичерпно для ASCII (Unicode \x00- \xff). Якщо ви це зробите, видаліть ці останні, оскільки вони можуть бути залучені до більш довгих послідовностей.


1

"tput sgr0" залишив цей керуючий символ ^ (B ^ [
Ось модифікована версія, щоб подбати про це.

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log

Дякую за це ... це працювало для мене, щоб позбутися того, tput sgr0що інших рішень, здається, ніколи не вдасться позбутися.
TxAG98

0

У мене були подібні проблеми із видаленням символів, доданих із збирання інтерактивного верхнього виводу за допомогою шпаклівки, і це допомогло:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'

3
Це марне використання cat( UUOC ) - це слід зробити . perl -pe command putty1.log
Скотт

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.