While writing script I noticed some very strange Perl behavior. The task is to trim last character of string stored in $temp1 variable, this can be done using either chop($temp1) or more complicated substr($temp1, 0, length($temp1) - 1). These both work as one-liners but in my script the substr solution does not work. Below is example from debugger:
1st PROBLEM:
1st SOLUTION – NOT WORKING:
main::(delmid_n.pl:24): if (($state == 0) && ($_ !~ $musr) && ($_ !~ $lusr)) {
>> n
main::(delmid_n.pl:54): $strprn=substr($temp1, 0, length($temp1) - 1);
>> p $temp1
(-,user2,t-mobile.co.uk)\
>> p substr($temp1, 0, length($temp1) - 1) . "\n";
(-,user2,t-mobile.co.uk)
DB<4>
main::(delmid_n.pl:55): print $strprn . "\n";
DB<4>
main::(delmid_n.pl:56): $temp1 = "";
DB<4>
As you can see in the $strprn variable, nothing is stored. If the same piece of code (which is stored into the $strprn variable) is printed via the ‘p’ command, the output is OK. This “bug” can be overcome using the mentioned chop() function (see code below):
2nd SOLUTION – WORKING:
main::(delmid_w.pl:24): if (($state == 0) && ($_ !~ $musr) && ($_ !~ $lusr)) {
>> p $temp1
(-,user2,t-mobile.co.uk)\
DB<4> n
main::(delmid_w.pl:56): chop ($temp1);
DB<4> n
main::(delmid_w.pl:57): print $temp1;
DB<4> n
(-,user2,t-mobile.co.uk)
main::(delmid_w.pl:58): $temp1 = "";
DB<4>
The above code is exactly the same as the first example, but the following two lines are from 1st example:
$strprn=substr($temp1, 0, length($temp1) - 1);
print $strprn . "\n";
are replaced with following two lines in the 2nd example:
chop ($temp1);
print $temp1;
What is wrong with the 2nd solution?
2nd PROBLEM:
This is a problem which I do not have a workaround for, so far.
DB<1>
main::(delbeg_n.pl:15): $state = 0;
DB<1>
main::(delbeg_n.pl:16): $muser = qr/\(-,user1,[^,]+\.co\.uk\)\\$/;
DB<1>
main::(delbeg_n.pl:19): line: while (<>) {
DB<1>
main::(delbeg_n.pl:20): chomp; # strip record separator
DB<1>
main::(delbeg_n.pl:21): @Fld = split(/\s+/, $_,);
DB<1>
main::(delbeg_n.pl:23): if (($state == 0) && ($Fld[1] =~ $muser)) {
DB<1> p $Fld[1]
(-,user1,one2one.co.uk)\
DB<2> n
main::(delbeg_n.pl:43): print $_;
DB<2> p $_
netgroup1 (-,user1,one2one.co.uk)\
DB<3> if ($Fld[1] =~ $muser) {print "TRUE"}
TRUE
As you can see after executing line 21 in the code, the next execution line is 43 (the else statement). Why is the following condition not evaluated as a true, allowing the code to continue with line 23, 24, 25?
if (($state == 0) && ($Fld[1] =~ $muser))
The following line was inserted as a demonstration that the condition should be evaluated as a true:
if ($Fld[1] =~ $muser) {print "TRUE"}
Thanks a lot.
Both problems are related. There is something strange at the end of the line.
First, it looks as if you have a newline character after the slash at the end of the line that you have not chomped off — at least that is what the debugger shows:
If there was no newline it would have been
So, there should be two characters:
\and newline.Why the weird behavior — I don’t know without looking at your input file.
Also, instead of using string length, you can just do
substr( $string, 0, -1 )— that will also return all but the last character.That is probably the reason for your second problem — I guess that
\(-,user1,[^,]+\.co\.uk\)\\matches and it is the end of line marker$that causes the mismatch.use strictplease