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

I'm trying to set $a to the value of $b if $a does not match $b. The substitution I came up with doesn't seem to be working though. Is this something that can't be done with substitution? Here is what I had come up with.
$a !~ s/$b/$b/;

Replies are listed 'Best First'.
Re: Replace $a with $b if $a ne $b
by Zaxo (Archbishop) on May 06, 2005 at 18:28 UTC

    Doesn't this do that directly? $a = $b; The conditional seems unnecessary since it has no effect.

    After Compline,
    Zaxo

      Take this values of $a and $b:

      $a = 12; $b = 2;

      From his words:

      if $a does not match $b

      I assume he wouldn't want to put the 2 in $a, as $a already matches $b.

Re: Replace $a with $b if $a ne $b
by JediWizard (Deacon) on May 06, 2005 at 18:22 UTC

    why not:

    $a = $b if($a ne $b);

    You should not be using $a and $b however, as they are "special" variables used by sort


    They say that time changes things, but you actually have to change them yourself.

    —Andy Warhol

      You should not be using $a and $b however, as they are "special" variables used by sort

      Doesn't matter. sort localizes $a and $b.

      $a = 1; print((sort { $b cmp $a } qw( a b c z y x )), $/); print($a, $/); # Prints "1"
        Does too matter. Try this code on perl 5.8.x.
        my $a = 1; print((sort { $b cmp $a } qw( a b c z y x )), $/); print($a, $/); # Prints "1"

      $a=$b if ($b ne $a);

      how can i do this another way, like a:

      +=,*=,.=,||=,..., etc

      ps: because my variable $a is very long, for example:

      $a{aaaaaaa1}{aaaaaaa2}{aaaaaaa3}=$b if ($b ne $a{aaaaaaa1}{aaaaaaa2}{aaaaaaa3});

      Thanks beforehand!

        Just do:

        $a = $b;

        The if clause is fairly redundant (unless you're concerned about one of the variables being a blessed object which overloads stringification).

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Replace $a with $b if $a ne $b
by ikegami (Patriarch) on May 06, 2005 at 18:25 UTC

    It's almost indentical to your subject:

    Replace $a with $b if $a ne $b
    $a = $b if $b ne $a;

    which simplifies to:

    $a = $b;

    Or maybe you wanted

    $a = $b unless $a =~ /$b/;
Re: Replace $a with $b if $a ne $b
by jhourcle (Prior) on May 06, 2005 at 19:55 UTC

    There are plenty of solutions already mentioned, but I thought I'd mention something about the code that you tried:

    $a !~ s/$b/$b/;

    There is no !~ when dealing with substitution, only with matching. If there was no match in a substitution, it didn't find anything to replace, and so won't do anything. You can do odd things with negative assertions, but I would assume you probably wanted to match:

    $a !~ m/$b/;

    But, we get into the question of 'match' ... in this case, if $a contains $b, the expression will be true. if you want to ensure that $a didn't have any extra characters, you'd want to match from the beginning of the string to the end:

    $a !~ m/^$b$/;

    But if $b contains any regular expression meta characters (parens, brackets, braces, asterisks, periods, question marks, etc), odd things may occur that you didn't want to happen. So, if you don't want that, you use:

    $a ne $b

    If you are looking for $b within $a, and there's a chance of meta characters, then you'll want to use a regex, but escape any character in $b that might not be safe.

Re: Replace $a with $b if $a ne $b
by cog (Parson) on May 06, 2005 at 18:25 UTC
    For what you say, it seems that this is what you want:

    unless ($a =~ /$b/) { $a = $b; }
Re: Replace $a with $b if $a ne $b
by Anonymous Monk on May 06, 2005 at 19:06 UTC
    I apologize, at the time of writing I thought it was clear. What is happening is I am looping through a list of files and I don't want to reprint the directory the files reside in for every single file. So I am trying to set $a to $b as $b changes and I am also setting $b to "" if it matches $a.
    foreach $file (@filelist) { ($dir, $name) = split '/', $file; $dir =~ s/$currentdir//; printf("%s %s\n", $dir, $name); $currentdir !~ s/$dir/$dir/; }
    so I will hopefully get output like
    DIR1 FILE1 FILE2 FILE3 DIR2 FILE4
      Once you've cleared $dir, it's useless to compare $currentdir to it. Maybe you want something like:
      my $printed_dir = ''; foreach $file (@filelist) { my ($dir, $name) = split '/', $file; printf("%s %s\n", ($dir eq $printed_dir ? '' : $dir), $name); $printed_dir = $dir; }

      Caution: Contents may have been coded under pressure.
      There are at least a few different (and sensible) ways to do what you want in that "foreach" loop. Personally, I'd opt for turning the list into a hash of arrays, so that it is structured in a way that is consistent with what the output should be:
      my %dirhash; for my $file ( @filelist ) { my ( $dir, name ) = split '/', $file; pushd @{$dirhash{$dir}}, $name; } for my $dir ( sort keys %dirhash ) { print "$dir\t", join( "\n\t", @{$dirhash{$dir}} ), "\n"; }
      Another way, more similar to your original idea, would be to keep track of what the last printed directory was, and only print the directory name when it changes from the previous:
      my $lastdir = ''; for my $file ( @filelist ) { my ( $dir, $name ) = split '/', $file; if ( $dir ne $lastdir ) { print "$dir"; $lastdir = $dir; } print "\t$name\n"; }
      You shouldn't use a regex to split the filename from the path. Better take File::Basename for that.
      use File::Basename; my ($name,$path) = fileparse($fullname);


      holli, /regexed monk/
Re: Replace $a with $b if $a ne $b
by Anonymous Monk on May 09, 2005 at 14:17 UTC
    Thank you all for you suggestions. There really are just so many ways to do things that at times it seems like they're hitting me in the face and I don't even notice. Also, thank you jhourcle for clearing up issue with the regular expressions. I was confused about that and hadn't found anything else to explain it.