I did a lot of searching on the scoping when using local.
I understand from here: http://www.perlmonks.org/?node_id=94007 that it changes temporarily the value of a variable in between when the "local" line is executed and when the next end of block is reached. However, it seems that it also "scrolls back" the perl reading cursor? It seems to keep the previous $_.
These are the requirements for my perl script:
On the std in, read a text file. if the current line matches ==, print the string on the line as html fragment with corresponding formating (different formating of each of ==, ===, ====) if it contains !, print the part before the ! as a property name and the part after the ! until the next ! as value(may span over multiple lines).
Here is a sample file:
$ cat dummy_spec.txt
== title1 (level 1) ==
=== title2 (level 2) ===
title2p2 !
2p2_1
!
title2p2 ! Line 1
!
title2p1 !
echo "$tam ta"
!
title2p3 !
2p3
!
title2p2 ! Li
ne split
!
==== title3 (level 3) ====
title3p1 !
one
two
three
!
And here is my code:
#!/usr/bin/env perl
my $propName='';
my $propVal='';
while (<>){
#print "new loop number $., contents $_ \n";
$propName='';
$propVal='';
my $str=$_;
chomp $str;
if ($str=~/==\s+.+\s+==/)#If line is a Category, print category
{
$str=~s/=//g;
print "\t\t\t<tr class=\"category\"><td colspan=\"2\">$str</td></tr>\n";
} elsif($str=~/===\s+.+\s+===/)#If line is a list, print list title
{
$str=~s/=//g;
print "\t\t\t<tr class=\"list\"><td colspan=\"2\">$str</td></tr>\n";
} elsif($str=~/====\s+.+\s+====/)#If line is an item, print item title
{
$str=~s/=//g;
print "\t\t\t<tr class=\"item\"><td>$str</td></tr>\n";
} elsif($str=~/!/)#If line is a property, print name and value
{
($propName,$propVal)=split '!', $_;
chop $propVal;
print "This is a property ($.) with name : $propName and first line : $propVal \n";
local $/ = "!\n";
if(<>){#custom $/ should still be in scope here.
chomp;
$propVal="$propVal -~- $_";
print "This is a property ($.) with name : $propName and value : $propVal \n";
}
}
}
The output is not what it should be:
$ cat dummy_spec.txt |./multi
<tr class="category"><td colspan="2"> title1 (level 1) </td></tr>
<tr class="category"><td colspan="2"> title2 (level 2) </td></tr>
This is a property (3) with name : title2p2 and first line :
This is a property (4) with name : title2p2 and value : -~- title2p2
This is a property (5) with name : title2p2 and first line : Line 1
This is a property (6) with name : title2p2 and value : Line 1 -~- title2p2 ! Line 1
This is a property (7) with name : title2p1 and first line :
This is a property (8) with name : title2p1 and value : -~- title2p1 !
This is a property (9) with name : title2p3 and first line :
This is a property (10) with name : title2p3 and value : -~- title2p3
This is a property (11) with name : title2p2 and first line : Li
This is a property (12) with name : title2p2 and value : Li -~- title2p2 ! Li
<tr class="category"><td colspan="2"> title3 (level 3) </td></tr>
This is a property (14) with name : title3p1 and first line :
This is a property (15) with name : title3p1 and value : -~- title3p1
it seems that it also "scrolls back" the perl reading cursor? It prints the previous $_.
I also apologize because my perl is very basic.
You're not assigning to $_
in the scope with your changed value of $/
, only
reading from the input and using the read line as the condition of an if
statement.
The magical assignment to the $_
variable when reading from a file only
happens if the <>
operator is the only contents of the condition of a while
loop, it doesn't apply to the condition of an if
statement. See the fourth
paragraph in the documentation for I/O Operators.
You likely want to change that if statement to:
if(defined ($_ = <>))