| Scalar-Quote documentation | Contained in the Scalar-Quote distribution. |
Scalar::Quote - Utility functions to quote Perl strings
use Scalar::Quote ':short';
$_=pack('c',rand 127) for (@a[0..1000]);
$s1=join '', @a;
$_=pack('c',rand 127) for (@b[0..1000]);
$s2=join '', @b;
$_=pack('c',rand 127) for (@c[0..40]);
$s3=join '', @c;
print "Q(\$s1)=",Q($s1),"\n";
print "S(\$a)=",S($a),"\n";
D($s3.$s1, $s3.$s2);
print "$a is not the same as $b\n";
print N(0), N(1), N(undef), N("hello"), "\n";
Several subrutines to quote scalars and spot differences between strings.
Mostly useful for debugging purposes.
quote $n as a number.
returns the string conveniently enclosed in single or double quotes, escaping unprintable and quoting chars as required.
quote the beginning of $string.
similar to substr($str, $start, $len) but adds a head or/and a tail
to the substring stating how many chars have been left out.
returns the index where the two strings start to differ or -1 if they are equal.
str_diff compares two strings and creates quoted versions of them
around the place where they start to differ.
D($s1, $s2) and print "$a is not the same as $b\n";
In scalar context the quoted strings are stored in globals $a and
$b on the caller package.
In list context the quoted strings are returned ($a and $b are
untouched).
When both strings are equal, undef or the empty list is returned.
Optional arguments $start and $len allow to configure the length
of the quoting. $start is the location to start the quote *after*
the differences begin, so it should be a negative number.
Nothing by default.
exports quote, quote_start, quote_cut and quote_number
exports str_diffix and str_diff subrutines.
exports Q, S, N and D.
Salvador Fandiño, <sfandino@yahoo.com>
Copyright 2002-2006 by Salvador Fandiño
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Scalar-Quote documentation | Contained in the Scalar-Quote distribution. |
package Scalar::Quote; our $VERSION = '0.26'; use 5.006; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'quote' => [ qw( quote quote_number quote_cut quote_start ) ], 'diff' => [ qw( str_diff str_diffix ) ], 'short' => [ qw( Q N S D ) ] ); our @EXPORT_OK = (@{$EXPORT_TAGS{quote}}, @{$EXPORT_TAGS{diff}}, @{$EXPORT_TAGS{short}}); our @EXPORT = qw(); # converts a char to its hex representation sub char_to_hex ($ ) { my $c=ord(shift); sprintf( ($c < 256 ? '\x%02x' : '\x{%x}'), $c); } my %esc = ( "\n" => '\n', "\t" => '\t', "\r" => '\r', "\\" => '\\\\', "\a" => '\a', "\b" => '\b', "\f" => '\f' ); sub escape_char($ ) { my $char=shift; exists $esc{$char} ? $esc{$char} : char_to_hex($char) } # converts unprintable chars to \x{XX} and also escapes '"' and '\' if # required sub Q ($ ) { my $s=shift; defined $s or return 'undef'; if ($s=~s/([^!#&()*+,\-.\/0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz{|}~ ])/escape_char($1)/ge) { return qq("$s"); } return qq('$s'); } *quote=\&Q; # compares two strings and returns the position where they start to be # diferent, i.e diffix('good morning', 'good afternoon') == 5 sub str_diffix ($$) { my ($a, $b)=@_; $a='' unless defined $a; $b='' unless defined $b; return -1 if $a eq $b; # my $c; # for (my $i=0;;$i++) { # $c=substr($a,$i,1); # return $i # unless ( $c ne '' and $c eq substr($b,$i,1)); # } my $la = length $a; my $lb = length $b; my $min = $la < $lb ? $la : $lb; my $c = substr($a, 0, $min) ^ substr($b, 0, $min); if ($c =~ m/[^\0]/g) { return pos($c) - 1; } return $min; } # quote_cut($string, $start, $len), like substr() but adds a head and a tail # to the substring reported how many chars have been left alone. It # also escapes the string. sub quote_cut ($$$ ) { return 'undef' unless defined $_[0]; my (undef, $start, $len)=@_; my $end=length($_[0])-$len-$start; if ($end<0) { $start+=$end; $end=0; } if ($start<0) { $start=0; } my $s=sprintf("[%d chars omitted]", $start); if (length $s>=$start) { $len+=$start; $start=0; $s=''; } my $e=sprintf("[%d chars omitted]", $end); if (length $e>=$end) { $len+=$end; $e=''; } quote($s.substr($_[0], $start, $len).$e); } # escape and quote string start operator, like Q but truncates the # string if it is to long. sub S ($;$ ) { my $len=defined $_[1] ? $_[1] : 32; quote_cut ($_[0], 0, $len); } *quote_start=\&S; my $number_re=qr/^\s*[+-]?(?:\d+|\d*\.\d*)(?i:E[+-]?\d+)?\s*$/; # quote number sub N ($ ) { no warnings; if (defined $_[0]) { if ($_[0]=~/$number_re/o) { return sprintf("%f", $_[0]); } return sprintf("%f (str: %s)", $_[0], S($_[0])); } 'undef' } *quote_number=\&N; # D computes the difference between two strings. sub D ($$;$$ ) { no warnings 'uninitialized'; return () if $_[0] eq $_[1]; my $len=defined $_[3] ? $_[3] : 32; my $start=(defined $_[2] ? $_[2] : -8) + str_diffix($_[0], $_[1]); my $a=quote_cut($_[0], $start, $len); my $b=quote_cut($_[1], $start, $len); return ($a, $b) if (wantarray); { no strict 'refs'; my $caller = caller; my $pa=$caller."::a"; my $pb=$caller."::b"; ${$pa}=$a; ${$pb}=$b; } return 1; } *str_diff=\&D; 1; __END__