http://www.perlmonks.org?node_id=684504


in reply to Wanted: humanly readable `script` output

What perl module can process the typescript file so I get a humanly readable ascii file?

To what end? Terminal captures include chars that are typed then erased, cursor positioning sequences, text colouring and so on. You can't convert terminal output into a "human readable ascii file" without loosing information which might be important to you, and you have a hard time converting terminal output into a human readable stream of information.

You could view the typescript file with less -R which renders escape sequences directly, but cursor movement sequences will blow it. Terminal output has been produced by the terminal, and your terminal is the program which groks the captured output, so use that.

If what you want is reading the terminal output again at a later time, capture that with

script -t typescriptfile 2> timingfile

to include timing information, then view it with 'scriptreplay'. Between <readmore> tags is the slightly hacked version I use to that end. Speeding up the output with a divisor lets you skim typescript files fast. I don't know of any better pager for typescript files. Update: adapted for use without timing file.

#!/usr/bin/perl -w use Getopt::Std; use Time::HiRes qw(ualarm); # "script -t" will output a typescript with timings # this script "scriptreplay" replays it # run pod2man on it to get a man page =head1 NAME scriptreplay - play back typescripts, using timing information =head1 SYNOPSIS scriptreplay -d [divisor] typescript timingfile =head1 DESCRIPTION This program replays a typescript, using timing information to ensure +that output happens at the same speed as it originally appeared when the sc +ript was recorded. It is only guaranteed to work properly if run on the sam +e terminal the script was recorded on. The timings information is what script outputs to standard error if it + is run with the -t parameter. By default, the typescript to display is assumed to be named "typescri +pt", but other filenames may be specified, as the second parameter. If the -d option is set, it is used as a time divisor. For example, specifying a divisor of 2 makes the script be replayed twice as fast. While the script is replayed, pressing the space bar pauses, pressing +q quits the replay. =head1 EXAMPLE % script -t 2> timingfile Script started, file is typescript % ls <etc, etc> % exit Script done, file is typescript % scriptreplay -d 8 typescript timingfile =head1 TODO =item Add a way to skip ff or seek back =cut use strict; $|=1; my $default_timing; # in case there's no timing file my %o; getopt('d',\%o); @ARGV or die "usage: $0 [-d divisor ] scriptfile timingfile\n"; my ($scriptfile, $timefile) = @ARGV; for ($timefile,$scriptfile) { my $f = $_; $f and $f =~ s/\.gz$// and system('gunzip',$_) or $_ = $f; } open (TYPESCRIPT, $scriptfile || 'typescript') or die "cannot read typescript: $!"; unless ($timefile and open (TIMING, $timefile)) { # or die "cannot read timing info: $!"; # no timing file, set default timing $default_timing = '0.000400 1'; } my $divisor = int($o{d}) || 1; my ($rout,$rin); $rin = ''; vec($rin,fileno(STDIN),1) = 1; system 'stty', 'cbreak','-echo'; my $doexit = 0; sub alarm_handler { # try to read a char from the terminal in non-blocking mode. # if we are successful and the char is a blank, read again, # blocking this time. my ($nfound,$timeleft) = select($rout=$rin, undef,undef, -1); if ($nfound) { my $char; read(STDIN,$char, 1); if ($char) { if ( $char eq ' ') { select($rout=$rin, undef,undef,1200); $char = getc STDIN; } if ($char eq 'q') { $doexit++; } $divisor++ if $char eq '+'; $divisor-- if $char eq '-' and $divisor > 1; } } ualarm(5000) unless $doexit;; } # Read starting timestamp line and ignore. <TYPESCRIPT>; $SIG{ALRM} = \&alarm_handler; ualarm(5000); my $block; my $oldblock=''; my $foo; while ($_ = $default_timing || <TIMING>) { my ($delay, $blocksize)=split ' ', $_, 2; # Sleep, unless the delay is really tiny. Really tiny delays c +annot # be accurately done, because the system calls in this loop wi +ll # have more overhead. The 0.0001 is arbitrary, but works fairl +y well. $delay = 2 * $divisor if $delay / $divisor > 2; # shorten idle + times if ($delay / $divisor > 0.0001) { my $timeleft = $delay / $divisor - 0.0001; while ($timeleft) { ($foo,$timeleft) = select(undef, undef, undef, $timeleft); } } read(TYPESCRIPT, $block, $blocksize) # or die "read failure on typescript: $!"; or $doexit++; print $oldblock; $oldblock=$block; last if $doexit; } print $oldblock; print "\n" if $doexit; system 'stty','-cbreak','echo'; =head1 SEE ALSO script(1) =head1 COPYRIGHT This program is in the public domain. =head1 AUTHOR Joey Hess <joey@kitenet.net> - hacked by shmem

--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}