Rob, can you explain the details of that replace?  That's pretty slick.  I
see you're adding the hex value to get to the appropriate ASCII value, but
didn't know you could do some of that gyration inside a regex.

Thanks.

-Tom Kinzer

-----Original Message-----
From: Rob Dixon [mailto:[EMAIL PROTECTED]
Sent: Tuesday, December 09, 2003 11:58 AM
To: [EMAIL PROTECTED]
Subject: Re: Pattern Match


Eric Sand wrote:
>
>     I am very new to Perl, but I sense a great adventure ahead after just
> programming with Cobol, Pascal, and C over the last umpteen years. I have
> written a perl script where I am trying to detect a non-printing
> character(Ctrl@ - Ctrl_) and then substitute  a printing ASCII sequence
such
> as "^@" in its place, but it does not seem to work as I would like. Any
> advice would be greatly appreciated.
>
>          Thank You....Eric Sand
>
>

Your obvious guess is to write Perl as if it were C. That's slightly better
than treating it as a scripting language, but there are many joys left to be
found!

> $in_ctr=0;
> $out_ctr=0;
>
> while ($line = <STDIN>)
>     {
>     chomp($line);
>     $in_ctr ++;
>     if ($line = s/\c@,\cA,\cB,\cC,\cD,\cE,\cF,\cG,\cH,\cI,\cJ,\cK,
>                   \cL,\cM,\cN,\cO,\cP,\cQ,\cR,\cS,\cT,\cU,\cV,\cW,
>                   \cX,\cY,\cZ,\c[,\c\,\c],\c^,\c_
>                  /^@,^A,^B,^C,^D,^E,^F,^G,^H,^I,^J,^K,
>                   ^L,^N,^N,^O,^P,^Q,^R,^S,^T,^U,^V,^W,
>                   ^X,^Y,^Z,^[,^\,^],^^,^_/)
>         {
>         $out_ctr ++;
>         printf("Non-printing chars detected in: %s\n",$line);
>         }
>     }
> printf("Total records read                                 =
%d\n",$in_ctr);
> printf("Total records written with non-printing characters =
%d\n",$out_ctr);

I would write this as below. The first things is to *always*

  use strict;
  use warnings;


after which you have to declare all of your variables with 'my'.

The second is to get used to using the default $_ variable which
is set to the value for the current 'while(<>)' or 'for' loop
iteration, and is a default parameter for most built-in functions.

Finally, in your particular case you're using the s/// (substitute)
operator wrongly. The first part, s/here//, is a regular expression,
not a list of characters. You'll need to read up on these at

  perldoc perlre

The second part, s//here/, is a string expression which can use
'captured' sequences (anything in brackets) from the first part
and, with the addition of the s///e (executable) qualifier can
also be an executable statement. Here I've used it to add 0x20
to the ASCII value of the control character grabbed by the regex.

A lot of this won't make sense until you learn some more, but I
hope you'll agree that this code is cuter than your original?

HTH,

Rob



use strict;
use warnings;

my $in_ctr = 0;
my $out_ctr = 0;

while (<>) {

  chomp;

  $in_ctr++;

  if (s/([\x00-\1F])/'^'.chr(ord($1) + 0x40)/eg) {
    $out_ctr++;
    printf "Non-printing chars detected in: %s\n", $_;
  }
}

printf "Total records read                                 = %d\n", $in_ctr;
printf "Total records written with non-printing characters = %d\n",
$out_ctr;



--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to