1
my $test = "_.4.1\n";
print $test;
my $docid=4;
$test =~ s/_.$docId.1/_.$docId.0/gm;
print $test

I was hoping to see:

_.4.1

_.4.0

But I get:

_.4.1

_.4.1

TLP
  • 66,756
  • 10
  • 92
  • 149
xyz
  • 8,607
  • 16
  • 66
  • 90

3 Answers3

8

You have a capital I in $docId in your regex, but declare it with a lower case i. $docid is not considered the same variable as $docId. Perl differentiates between upper and lower case inside variable names.

You should always use

use strict;
use warnings;

To prevent simple errors like this.

See also: Why use strict and warnings?

Community
  • 1
  • 1
TLP
  • 66,756
  • 10
  • 92
  • 149
  • 3
    As a simple habbit, I always use perl -w – Nikodemus RIP Dec 15 '11 at 09:21
  • 2
    Why would you use `-w`, when the more flexible and powerful alternative, `use warnings` was added to Perl over ten years ago? – Dave Cross Dec 15 '11 at 09:59
  • 1
    Because it is very simple to always set -w even on a -e oneliner. – Nikodemus RIP Dec 15 '11 at 10:02
  • @Nikodemus: Agreed. I wish there was an switch for `use strict` too, so I could avoid `perl -Mstrict -we '...'`. – flesk Dec 15 '11 at 13:46
  • It's not do one or do the other. "use warning" is good style. But sometimes you need to test a thing on don't know where the problem is. -w is a quick way to get additional information. – Nikodemus RIP Dec 15 '11 at 13:51
  • @Nikodemus For one-liners, `-w` is often perfectly fine. @flesk `-M5.012` activates strict, saving a whopping 2 characters. Or in *nix, make an alias `p perl -Mstrict -wE` ;) – TLP Dec 15 '11 at 14:03
1

Perl 5.10 has a nice feature that makes this problem easier. a \K in the pattern portion of the substitution operator tells it to not replace anything before the \K. That way, you can make the pattern to locate the bit that you want to change, but then only replace the part that doesn't change:

use v5.10;
use strict;
use warnings;

my $test = "_.4.1";
say $test;

my $docId=4;
$test =~ s/_\.$docId\.\K1/0/;

say $test;

I removed the /g and /m flags because they don't do anything in your example.

If you aren't using v5.10 yet (and it's one of the unsupported versions now), you can get the same effect with a positive lookbehind (as long as it's a constant width pattern):

use strict;
use warnings;

my $test = "_.4.1";
print "$test\n";

my $docId = 4;
$test =~ s/(?<=_\.$docId\.)1/0/;

print "$test\n";
brian d foy
  • 129,424
  • 31
  • 207
  • 592
-1

Try using the -w option in perl

_.4.1
Use of uninitialized value $docId in regexp compilation at test.pl line 4.
_.4.1


$docid != $docId;
Nikodemus RIP
  • 1,369
  • 13
  • 20
  • 4
    Before you recommend the global `-w` switch over the lexical `warnings` pragma next time, learn the difference: http://stackoverflow.com/questions/221919/should-i-turn-on-perl-warnings-with-the-command-line-switch-or-pragma – daxim Dec 15 '11 at 09:46