From: Paul Lalli on
A coworker just presented me with this task. I came up with two
solutions, but I don't like either of them. He has a text document
and wants to scan it for characters such as newline, tab, form feed,
carriage return, vertical tab. If found, he wants to replace them
with their typical representation (ie, \n, \t, \f, \r, \v).

I first gave him the obvious:
$string =~ s/\n/\\n/;
$string =~ s/\t/\\t/;
$string =~ s/\f/\\f/;
$string =~ s/\r/\\r/;
$string =~ s/\v/\\v/;

which I don't like because of how much copy/paste is involved. Then I
came up with:

for (qw/n t f r v/) {
my $meta = eval("\\$_");
$string =~ s/$meta/\\$_/;
}

which I don't like, because the comment he'd have to put in the code
to explain it would be longer than the code itself, or the first
version.

So can anyone think of a better way? Is there any kind of intrinsic
link between a newline character and the letter 'n' that could be used
to go "backwards" here?

Thanks,
Paul Lalli
From: Uri Guttman on
>>>>> "PL" == Paul Lalli <mritty(a)gmail.com> writes:

PL> A coworker just presented me with this task. I came up with two
PL> solutions, but I don't like either of them. He has a text document
PL> and wants to scan it for characters such as newline, tab, form feed,
PL> carriage return, vertical tab. If found, he wants to replace them
PL> with their typical representation (ie, \n, \t, \f, \r, \v).

PL> I first gave him the obvious:
PL> $string =~ s/\n/\\n/;
PL> $string =~ s/\t/\\t/;
PL> $string =~ s/\f/\\f/;
PL> $string =~ s/\r/\\r/;
PL> $string =~ s/\v/\\v/;

PL> which I don't like because of how much copy/paste is involved. Then I
PL> came up with:

use a hash table for the conversion:

my %controls = (
"\n" => '\\n',
"\t" => '\\t',
"\r" => '\\r',
"\f" => '\\f',
"\v" => '\\v',
) ;

$string =~ s/([\n\t\r\f\v])/$controls{$1}/g;

and if you want to get anal about dups of the chars do this:

my @controls = qw( n t r f v ) ;
my %control_to_escape = map { eval( "\\$_" ) => "\\$_" } @controls ;

my $controls_re = '[' . join( '', map "\\$_", @controls ) . ']' ;

$string =~ s/($controls_re)/$controls_to_escape{$1}/g;

see ma! only one use of the actual control letters!

uri

--
Uri Guttman ------ uri(a)stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
From: sln on
On Mon, 2 Nov 2009 11:07:56 -0800 (PST), Paul Lalli <mritty(a)gmail.com> wrote:

>A coworker just presented me with this task. I came up with two
>solutions, but I don't like either of them. He has a text document
>and wants to scan it for characters such as newline, tab, form feed,
>carriage return, vertical tab. If found, he wants to replace them
>with their typical representation (ie, \n, \t, \f, \r, \v).
>
>I first gave him the obvious:
>$string =~ s/\n/\\n/;
>$string =~ s/\t/\\t/;
>$string =~ s/\f/\\f/;
>$string =~ s/\r/\\r/;
>$string =~ s/\v/\\v/;
>
>which I don't like because of how much copy/paste is involved. Then I
>came up with:
>
>for (qw/n t f r v/) {
> my $meta = eval("\\$_");
> $string =~ s/$meta/\\$_/;
>}
>
>which I don't like, because the comment he'd have to put in the code
>to explain it would be longer than the code itself, or the first
>version.
>
>So can anyone think of a better way? Is there any kind of intrinsic
>link between a newline character and the letter 'n' that could be used
>to go "backwards" here?
>

Yet another way..

use strict;
use warnings;

my %translation = (
'\n'=>"\n",
'\t'=>"\t",
'\f'=>"\f",
'\r'=>"\r",
# ,'\v'=>"\v" - no 'v' for 'm'e, vt?
);

my $sample = "line 1\tsome\nline 2\t\t\f\n\rline 3\n";

while (my ($literal,$actual) = each %translation) {
$sample =~ s/$actual/$literal/eg;
}

print $sample;

__END__

-sln
From: Randal L. Schwartz on
>>>>> "Uri" == Uri Guttman <uri(a)StemSystems.com> writes:

>>>>> "PL" == Paul Lalli <mritty(a)gmail.com> writes:
PL> A coworker just presented me with this task. I came up with two
PL> solutions, but I don't like either of them. He has a text document
PL> and wants to scan it for characters such as newline, tab, form feed,
PL> carriage return, vertical tab. If found, he wants to replace them
PL> with their typical representation (ie, \n, \t, \f, \r, \v).

PL> I first gave him the obvious:
PL> $string =~ s/\n/\\n/;
PL> $string =~ s/\t/\\t/;
PL> $string =~ s/\f/\\f/;
PL> $string =~ s/\r/\\r/;
PL> $string =~ s/\v/\\v/;

PL> which I don't like because of how much copy/paste is involved. Then I
PL> came up with:

Uri> use a hash table for the conversion:

Uri> my %controls = (
Uri> "\n" => '\\n',
Uri> "\t" => '\\t',
Uri> "\r" => '\\r',
Uri> "\f" => '\\f',
Uri> "\v" => '\\v',
Uri> ) ;

Just to scare people:

my %controls = (
"\n" => '\n',
"\t" => '\t',
"\r" => '\r',
"\f" => '\f',
"\v" => '\v',
);

Ok, that's downright evil. :)

print "Just another Perl hacker,"; # the original

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn(a)stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
From: sln on
On Mon, 02 Nov 2009 12:21:06 -0800, sln(a)netherlands.com wrote:

>On Mon, 2 Nov 2009 11:07:56 -0800 (PST), Paul Lalli <mritty(a)gmail.com> wrote:
>
>while (my ($literal,$actual) = each %translation) {
> $sample =~ s/$actual/$literal/eg;
$sample =~ s/$actual/$literal/g;
-sln
 |  Next  |  Last
Pages: 1 2 3
Prev: unintialised warning
Next: optimizar r/w en ficheros