jcrush has asked for the wisdom of the Perl Monks concerning the following question:

Hello Wise Monks,
I'm trying to find a more efficient solution, to correct interpolated data coming into my script.
Since I cannot control the data coming in - only how its stored in the database.
I'm storing data into a SQL database that is interpolating domain accounts into whitespace.

Incoming data, 3 types of samples interpolated:

"AD\thomas" -> "AD homas" # tab "MAIN\nancy" -> "MAIN ancy" # newline "nancy" -> "nancy" # no domain, no problem

Here is what I came up with, but its a kludge, and not efficient when working with lots of database inserts.

$domainID =~ (s/(AD|MAIN)\n/n/); # should not be $domainID =~ (s/(AD|MAIN)\r/r/); # checked 3 times $domainID =~ (s/(AD|MAIN)\t/t/); # before exiting

- - - SOLUTION - - -

Thanks to everyone's suggestions, I solved this domain interpolation issue:

our %whitespace = ( "\f" => "f","\n" => "n","\r" => "r","\t" => "t" ); $netid =~ (s/(\s)/$whitespace{$1}/g); $netid =~ (s/(AD|MAIN)//);

Results:

"AD\thomas" -> "thomas" "MAIN\floyd" -> "floyd" "AD\manny" -> "manny" # perl escapes normal char, no harm

Thank you for all the help,

jcrush

Replies are listed 'Best First'.
Re: Efficiently create an IF/ELSE regex
by hdb (Monsignor) on May 01, 2015 at 16:22 UTC

    If there are no other spaces:

    use strict; use warnings; my @incoming = ( "AD\thomas", "MAIN\nancy", "FOO\randy", "nancy", ); my %whitespace = ( "\n" => "n", "\t" => "t", "\r" => "r", "\f" => "f", ); for (@incoming) { print "$_: "; s/(\s)/\\$whitespace{$1}/g; print "$_\n"; }

    (stealing some code from above...)

      Thank you, this is what I was looking for:

      my %whitespace = ( "\n" => "n", "\t" => "t", "\r" => "r", "\f" => "f", ); my $fixid =~ s/(\s)/\\$whitespace{$1}/g;

      I find it more efficient to complete a full test, than test multiple times.

      Thanks,

      jcrush

        Unless you want to modify default variable $_ & save the number of replacements, there is typo in your s/// application. In that case, op should be (to save the result of all of replacements in another string) ...

        ( my $fixed = $input ) =~ s/ search / replace /x;

        For fun, try the proposed s/(\s)/\\$whitespace{$1}/g solution on string x y (a plain space in between).

Re: Efficiently create an IF/ELSE regex
by jeffa (Bishop) on May 01, 2015 at 15:51 UTC

    So what you are saying is that instead of receiving 'AD\thomas' you are receiving 'AD    homas' and you want to reverse construct the original string? Why are you receiving garbage data? Garbage in/garbage out ... but in the off chance that yes, this is the hand you have been dealt then this should do the trick:

    my @incoming = ( "AD\thomas", "MAIN\nancy", "FOO\randy", "nancy", ); s/\t/\\t/ for @incoming; s/\n/\\n/ for @incoming; s/\r/\\r/ for @incoming; print $_, $/ for @incoming;
    I'll leave it to someone else to condense that into one neat regex. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Efficiently create an IF/ELSE regex
by AnomalousMonk (Archbishop) on May 01, 2015 at 15:52 UTC

    Not exactly sure what you want, but maybe something like (needs 5.10+ for \K):

    c:\@Work\Perl>perl -wMstrict -le "use 5.010; ;; my %xlate = (qq{\n} => 'n', qq{\t} => 't', qq{\r} => 'r'); my $interp = join '', keys %xlate; $interp = qr{ [\Q$interp\E] }xms; print $interp; ;; my $pre = qr{ AD | MAIN }xms; ;; for my $s (qq{AD\thomas}, qq{MAIN\nancy}, qq{nancy}) { printf qq{'$s' -> }; (my $t = $s) =~ s{ $pre \K ($interp) }{$xlate{$1}}xmsg; print qq{'$t'}; } " \?^msx: [\ \ ] ) 'AD homas' -> 'ADthomas' 'MAIN ancy' -> 'MAINnancy' 'nancy' -> 'nancy'


    Give a man a fish:  <%-(-(-(-<