1

Is there a tool to robustly render a text with escape sequences (eg a terminal log) ?

This question is related to render text with escape squence (like a terminal) (My edits to that question were rejected so I'm posting a new one here with a concrete new use case; the answers to the above question fail to address this use case).

For example, I'd like to search for a string in a terminal log and only search for strings actually displayed, eg:

$script terminal_log.txt
logging to terminal_log.txt
$echo bar<BACKSPACE><BACKSPACE><BACKSPACE>foo
foo
$cat terminal_log.txt|grep -c bar
1
$cat terminal_log.txt|sometool|grep -c bar
0

sometool would render the text by completely removing bar (which was deleted by user with 3 backspaces) exactly as shown in the terminal output, whereas cat doesn't remove it.

[edit] here is another example that shows the proposed col -b doesn't work:

$echo bar
bar
$clear 
#the screen is cleared
$cat terminal_log.txt
#nothing shown, in particular no bar
$cat terminal_log.txt|col -b|grep -c bar
2

We get 2 instead of 0 even though cat terminal_log.txt doesn't show bar (it's hidden due to the terminal sequences). So the utility col -b doesn't handle terminal commands such as clear etc. What I'm looking for is a utility that would render exactly what is displayed on the terminal.

Community
  • 1
  • 1
timotheecour
  • 3,104
  • 3
  • 26
  • 29

2 Answers2

1

The command you need for resolving the backspaces is col -b. I found it here.

$ cat terminal_log.txt | col -b | grep -c bar
0
$

Resolving clear will be much harder, especially in a robust, portable, terminal-independent manner. I am trying with two different terminal emulators - traditional xterm and gnome-terminal (Ubuntu 12.04). In both cases, clear appears to emit the escape sequence:

1b5b 481b 5b32 4a1b 5d30 3b75

But the terminal emulators interpret this differently:

  • xterm, really does clear the screen as you describe - the previous 24 or so rows are deleted from the scrollback buffer.
  • However gnome-terminal does not actually delete any rows. Instead it appears some sort of anchor is created at the clearing point and the terminal scrolled such that the anchor is at the top of the terminal window. If you scroll back, you will see no lines have been deleted at all. In this case, if I have script typescript file in which I did just a clear, and cat that file to the screen, I can scroll to view the entire file - no rows are deleted.

So depending on which terminal emulator you are using, you may or may not want to delete rows at all.

Now, assuming you are happy with just the xterm-dependent behavior, it would be possible to write a script which searches for this escape sequence and deletes $LINES number of rows before it in the typescript file. However this is not robust as the terminal may have been resized since script was run, and $LINES would be incorrect. The number of rows to be deleted does not appear to be encoded into the escape sequence.

Community
  • 1
  • 1
Digital Trauma
  • 15,475
  • 3
  • 51
  • 83
  • added test case with `clear` to show this isn't enough. – timotheecour Feb 27 '14 at 03:05
  • Furthermore, even for the case of backspaces this doesn't seem to work: `$ echo zobbaz` and then `cat terminal_log.txt | col -b` returns `$ echo zoKbaz` instead of `$ echo baz` – timotheecour Feb 27 '14 at 04:20
  • @timotheecour - see my edit; I attempt to explain why this probably is not possible in a robust manner for `clear`. – Digital Trauma Feb 27 '14 at 04:36
  • @timotheecour - yes, you're right - I think `col -b` is just deleting the `\b` character, but not all the associated escape characters that end up in the typescript file. I guess this needs more work/research. – Digital Trauma Feb 27 '14 at 04:58
  • I don't see how could `clear` could ever delete log file, the file is only ever appended (AFAIK). I've tried with xterm (on osx); typing clear merely scrolls to top so it appears as if lines were deleted but clearly everything that was written to log file is still there as can be shown via `cat terminal_log.txt|wc -l`. – timotheecour Feb 27 '14 at 23:28
0

I found a very hacky way to achieve that to some extent and can be scripted completely (at least on OSX; please contribute for linux).

given a file $file (eg terminal_log.txt):

render_control_chars $file does the following:

1. open a new terminal window T via applescript 2. cat $file 3. call applescript to CMD+A;CMD+C (copy all to clipboard) 4. a=$(pbpaste) 5. close T via applescript 6. cat $a to stdout

Additionally we can save the pbpaste before calling CMD+A;CMD+C and then restore it to avoid modifying the clipboard.

Actually this works with commands that erase/manipulate terminal buffer/cursor (eg: tput cuu 1; tput el or backspace or less followed by q) which is a common case. It doesn't work with clear somehow (eg on xterm) as the clear only moves cursor to top of terminal but terminal is still scrollable (unlike commands that erase/manipulate cursor).

So clearly something is possible. Any way to improve? Any way to get rid of applescript? How about on linux?

timotheecour
  • 3,104
  • 3
  • 26
  • 29