Видалення символів керування (включаючи консолі / кольори) з виводу сценарію


68

Я можу використовувати команду "script" для запису інтерактивного сеансу в командному рядку. Однак це включає всі контрольні символи та кольорові коди. Я можу видалити контрольні символи (наприклад, зворотну простір) за допомогою "col -b", але не можу знайти простий спосіб видалити кольорові коди.

Зауважте, що я хочу використовувати командний рядок у звичайному порядку, тому не хочу відключати кольори там - я просто хочу видалити їх із вихідного сценарію. Крім того, я знаю, що можна пограти і спробувати знайти регулярний вираз, щоб виправити речі, але я сподіваюся, що існує більш просте (і більш надійне - що робити, якщо є код, про який я не знаю, коли розробляю регексп?) Рішення.

Щоб показати проблему:

spl62 tmp: сценарій
Сценарій запущений, файл - це машинопис
spl62 lepl: ls
add-licence.sed build-example.sh commit-test push-docs.sh
add-licence.sh build.sh delete-licence.sed setup.py
asn build-test.sh delete-licence.sh src
build-doc.sh чистий doc-src test.ini
spl62 lepl: вихід
Сценарій виконаний, файл - це машинопис
spl62 tmp: cat -v машинопис
Сценарій розпочався в четвер 09 червня 2011 09:47:27 CLT
spl62 lepl: ls ^ M
^ [[0m ^ [[00madd-licence.sed ^ [[0m ^ [[00; 32mbuild-example.sh ^ [[0m ^ [[00mcommit-test ^ [[0m ^ [[00; 32mpush-docs.sh ^ [[0м ^ М
^ [[00; 32madd-licence.sh ^ [[0m ^ [[00; 32mbuild.sh ^ [[0m ^ [[00mdelete-licence.sed ^ [[0m ^ [[00msetup.py ^ [[0m ^ M
^ [[01; 34masn ^ [[0m ^ [[00; 32mbuild-test.sh ^ [[0m ^ [[00; 32mdelete-licence.sh ^ [[0m ^ [[01; 34msrc ^ [[0m ^ M
^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^ [[0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^ [[0m ^ M
spl62 lepl: вихід ^ М

Сценарій зроблено в Четвер 09 червня 2011 09:47:29 CLT
spl62 tmp: col -b <машинопис 
Сценарій розпочався в четвер 09 червня 2011 09:47:27 CLT
spl62 lepl: ls
0m00madd-licence.sed0m 00; 32mbuild-example.sh0m 00mcommit-test0m 00; 32mpush-docs.sh0m
00; 32madd-licence.sh0m 00; 32mbuild.sh0m 00mdelete-licence.sed0m 00msetup.py0m
01; 34masn0m 00; 32mbuild-test.sh0m 00; 32mdelete-licence.sh0m 01; 34msrc0m
00; 32mbuild-doc.sh0m 00; 32mclean0m 01; 34mdoc-src0m 00mtest.ini0m
spl62 lepl: вихід

Сценарій зроблено в Четвер 09 червня 2011 09:47:29 CLT

Відповіді:


57

Наступний скрипт повинен відфільтрувати всі послідовності управління ANSI / VT100 / xterm для (на основі ctlseqs ). Мінімально перевірені, повідомляйте про будь-який недобіг чи перевищення матчу.

#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \e\[ [ -?]* [@-~] | # CSI ... Cmd
       \e\] .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       \e[P^_] .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e. //xg;
    print;
}

Відомі проблеми:

  • Не скаржиться на неправильно сформовані послідовності. Це не для чого цей сценарій.
  • Багаторядкові рядкові аргументи для DCS / PM / APC / OSC не підтримуються.
  • Байти в діапазоні 128–159 можуть бути проаналізовані як контрольні символи, хоча це рідко використовується. Ось версія, яка аналізує символи управління, що не належать до ASCII (це змінить текст, який не є ASCII, у деяких кодуваннях, включаючи UTF-8).
#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
    print;
}

завдяки обом відповідям. Я відчував, що я повинен зробити щось як хорошу відповідь, хоча обидва дають регепси, чого я хотів уникнути. вибрав цей, оскільки він дає посилання на формат.
andrew cooke

@andrew: Мій regexp є досить гнучким, що я очікую, що він буде працювати з майже будь-яким уже існуючим терміналом, і, мабуть, і з будь-яким завтра існуючим терміналом. Я не тестував його багато, тому можуть бути помилки, але підхід є здоровим, оскільки контрольні послідовності дотримуються кількох загальних зразків.
Жиль

вкажіть, будь ласка, як користуватися цим сценарієм. це вимагає введення труби? чи позиційні аргументи?
Тревор Бойд Сміт

@TrevorBoydSmith Або буде працювати для введення даних, і вихід завжди на стандартному виході, як типові текстові утиліти.
Жиль

Це обманює багатобайтові символи, такі як ☺ (\ xe2 \ x98 \ xba). Стаття [\ x80- \ x9f] позбавляє середнього байту.
Джефрі

31

Оновлення відповіді Жиля також видаляти повернення каретки та виконувати стирання попередніх символів, які були для мене важливими для машинописного файлу, сформованого на Cygwin:

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

+1 Я вже набирав допис із тим же запитом, що і ОП, коли мені подобалося це повідомлення вашим сценарієм та повідомленням @Gilles. +1 для вас обох
чудо173

10

Я б використовував sedу цьому випадку.

робити:

cat -v typescript | sed -e "s/\x1b\[.\{1,5\}m//g"

sed -e "s / пошук / заміна / g" - це стандартний матеріал. регулярний вираз пояснюється так:

\x1bвідповідати Escape, що передує кольоровому коду, \[відповідає першій відкритій дужці, що .\{1,5\}відповідає 1 - 5 будь-якого окремого символу. Доведеться до \фігурних брекетів, щоб оболонка не манила ними. mОстанній символ у регулярному виразі - зазвичай відстежує колірний код. //порожній рядок на що замінити все. gзбігайте його кілька разів за рядок.


3
Це регулярний вираз смужка занадто багато ( foo\e[1m(1m = {стає foo = {замість foo(m = {), замінивши .на [0-9;]більш точна.
Лекенштейн

Замінити .\{1,5\}з [^m]\{1,5\}для цього - але зверніть увагу , що навіть тоді ще тільки видаляє «графічні видач» коди (ті , які закінчуються в m) - в основному колір, реверс, напівжирний і курсивний стилі (де це можливо).
Hannu

Це не видаляється \x1b(B(входить до виведення кольорів іржі)
ideaman42

1
Чому це так \x1bі ні \033?
atripes

Це може бути \u001bзамість\x1b
yunzen


6
# The "sed -r" trick does not work on every Linux, I still dunno why:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

=> як користуватися:

<commands that type colored output> | ${DECOLORIZE}

тестовано на: - AIX 5.x / 6.1 / 7.1 - Linux Mandrake / Mandriva / SLES / Fedora - SunOS


3

Я вирішив проблему, запустивши scriptreplayекран і скидаючи буфер прокрутки у файл.

Наступний сценарій очікування робить це для вас.

Він перевірений на логістичні файли, що містять до 250 000 рядків. У робочому каталозі вам потрібен ваш скрипт-файл, файл під назвою "час", який у 10 000 000 разів перевищує рядок "1 10" в ньому, і сценарій. Мені потрібна назва вашого скрипт-файлу як аргумент командного рядка, наприклад ./name_of_script name_of_scriptlog.

#!/usr/bin/expect -f 

set logfile [lindex $argv 0]

if {$logfile == ""} {puts "Usage: ./script_to_readable.exp \$logfile."; exit}

set timestamp [clock format [clock sec] -format %Y-%m-%d,%H:%M:%S]
set pwd [exec pwd]
if {! [file exists ${pwd}/time]} {puts "ERROR: time file not found.\nYou need a file named time with 10.000.000 times the line \"1 10\" in the working directory for this script to work. Please provide it."; exit}
set wc [exec cat ${pwd}/$logfile | wc -l]
set height [ expr "$wc" + "100" ]
system cp $logfile ${logfile}.tmp
system echo $timestamp >> ${logfile}.tmp
set timeout -1
spawn screen -h $height -S $timestamp 
send "scriptreplay -t time -s ${logfile}.tmp 100000 2>/dev/null\r"
expect ${timestamp} 
send "\x01:hardcopy -h readablelog.${timestamp}\r"

send "exit\r"

system sed '/^$/d' readablelog.$timestamp >> readablelog2.$timestamp
system head -n-2 readablelog2.$timestamp >> ${logfile}.readable.$timestamp
system rm -f readablelog.$timestamp readablelog2.$timestamp ${logfile}.tmp

Файл часу може бути створений

for i in $(seq 1 10000000); do echo "1 10" >> time; done

Команда для генерування файлу часу генерувала 100% використання процесора протягом декількох хвилин, а після закінчення використання моєї пам'яті було 100%, а виконання команди призвело до "fork: не може виділити пам'ять". І це насправді не спрацювало так, як очікувалося.
barteks2x

Існує набагато простіший спосіб генерувати файл часу. Поля є " delay blocksize", тому немає причин не просто " 0 <entirefile>" зробити це і не скинути всю справу без затримки. Ви можете зробити це, взявши розмір сценарію мінус перший рядок ( tail -n +2 typescript|wc -c), і створити файл хронометражу echo "0 "`tail -n +2 typescript|wc -c` > timing. Це в основному миттєво, і scriptreplayбуде відтворювати весь сценарій з максимально швидкою швидкістю.
FeRD

1

Знайшов це питання, шукаючи рішення тієї ж проблеми. Трохи більше копав і знайшов цей сценарій у Live Journal за цим посиланням. Я прекрасно працював для мене. Це також дуже добре написати про цю проблему та про те, як працює рішення. Однозначно варто прочитати. http://jdimpson.livejournal.com/7040.html

#!/usr/bin/perl -wp

# clean up control characters and other non-text detritus that shows up 
# when you run the "script" command.

BEGIN {
# xterm titlebar escape sequence
$xtermesc = "\x1b\x5d\x30\x3b";

# the occurence of a backspace event (e.g. cntrl H, cntrol W, or cntrl U)
$backspaceevent = "\x1b\\\x5b\x4b"; # note escaping of third character

# ANSI color escape sequence
$ansiesc = qr/\x1b\[[\d;]*?m/;

# technically, this is arrow-right. For some reason, being used against
# very long backspace jobs. I don't fully understand this, as evidenced
# by the fact that is off by one sometimes.
$bizarrebs = qr/\x1b\[C/;

# used as part of the xterm titlebar mechanism, or when
# a bell sounds, which might happen when you backspace too much.
$bell = "\x07"; # could use \a

$cr = "\x0d"; # could use \r

$backspace = "\x08"; # could use \b
}

s/$xtermesc.+?$bell//g;
s/[$cr$bell]//g;
s/${backspaceevent}//g;
s/$ansiesc//g;
while (s/(.)(?=$backspace)//) { s/$backspace//; } # frickin' sweet 
# For every ^H delete the character immediately left of it, then delete the ^H.
# Perl's RE's aren't R, so I wonder if I could do this in one expression.
while (s/(..)(?=$bizarrebs)//) { s/$bizarrebs//; }

1

Я вважаю за краще використовувати спеціалізовані інструменти для перетворення виводу скриптів у звичайний текст, який постійно підтримується і добре перевіряється, за допомогою спеціального regexp. Отже, це зробило роботу для мене:

$ cat typescript | ansi2txt | col -bp > typescript.txt.bp    
$ cat -v typescript.txt.bp

Команда скрипта захоплює файл шрифтів ansi2txt - перетворює ansi-код із втечами, такими як кольорові коди, зворотні простори тощо, у звичайний текст, проте я виявив, що пара залишається втечею. col -bp - видалено їх повністю.

Я тестував це на останній дискотеці Ubuntu, і це працює.


1

У пакеті Ubuntu є ansi2txtкоманда colorized-logs. Він прекрасно видаляє кольори ANSI кольорів, але він не стосується таких речей, як смуги прогресу, що створюються випромінюванням ^Hабо ^Mсимволами для перезапису тексту на місці. col -bможна вирішити це , тому для найкращих результатів ви можете поєднати ці два

cat typescript | ansi2txt | col -b

0

Я виявив, що просто використовувати catбуло все, що мені потрібно для перегляду виходу scriptв терміналі. Це не допомагає , коли перенаправивши висновок в інший файл, але робить результат читання, в відміну від cat -v, col -bабо в текстовому редакторі.

Щоб усунути кольори або зберегти результати у файл, скопіюйте та вставте результат вручну catв текстовий редактор або в іншу catкоманду, тобто:

cat > endResult << END
<paste_copied_text_here>
END

1
Чи scriptвключав ваш пробіг вихід з доданими кольоровими кодами, як у випадку з ОП?
Джефф Шаллер

Використовуючи catпредставлені оригінальні кольори, які можна видалити за допомогою копіювання та вставки вручну. ОП використовував cat -vі col -bобидва з них представляють коди, а не правильно відформатований кінцевий результат. Я відредагував свою відповідь.
Роджер Дуек

-2

Слідкуючи за останньою відповіддю, в якій використовується tr і: cntrl: ми могли б зробити

sed "/^[[:cntrl:]]/d" output.txt

Здається, це працює для мене, тому що всі рядки, згенеровані vi, починаються з символу управління. Трапляється також викреслити порожні рядки та рядки, які починаються з вкладки, хоча це працює для того, що я роблю. Можливо, є спосіб зіставити будь-який контрольний символ, крім \ n \ m \ t.

Можливо, ми можемо шукати конкретного керуючого символу, і це виглядає так, що всі непотрібні лінії, породжені vi, починаються з того, що схоже на ^ [. hexdump каже мені, що перший символ - 1b, тому, здається, це теж працює

sed "/^\x1b/d" output.txt

Це схоже на відповідь, розміщену вище, але вона не працює належним чином, оскільки після запуску команди деякі непотрібні символи вже додаються до командного рядка так, ніби користувач ввів їх.


1
Немає "останньої відповіді", оскільки відповіді можуть змінити порядок. Вам слід скористатися кнопкою "поділитися" під відповіддю, на який ви хочете посилатися, і включити її як посилання у своїй відповіді. Якщо припустити, що ваша відповідь достатня, звичайно, щоб бути більше, ніж коментар. Зараз я не можу визначити, на який із кількох відповідей ви посилаєтесь.
roaima

1
«Ми могли б , можливо , зробити ...» Так, ми могли б зробити це , - але це буде видалити кожен рядок , яка починається з керуючим символом . Наприклад, на виході, наприклад, ls --color(як показано у запитанні), ваше рішення видалить майже кожен рядок, що містить інформацію. Не добре. Але дякую за те, що залишили марне використання cat. :-) ⁠
G-Man

Чи є спосіб створити клас символів, який є: iscntrl: але ні: isspace :? Можливо, такий синтаксис, як ^ [[: iscntrl:] - [: isspace]]
snaran

-4

tr - перекладати або видаляти символи

cat typescript | tr -d [[:cntrl:]]

Ласкаво просимо в Unix Stackexchange! Коли ви даєте відповідь, бажано дати пояснення щодо того, ЧОМУ ваша відповідь .
Стівен Рауч

Стислість прийнятна, але більш повні пояснення краще. , також не зовсім вирішує цю проблему тут.
Kusalananda

3
Це насправді не буде працювати належним чином, оскільки, наприклад, не видалить 01;34mприклад та видалить кінець рядка newline (\n).
соронтар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.