Home: Perl Programming Help: Intermediate:
Substitution Gone Awry

New User

Feb 7, 2008, 11:37 AM

Views: 333
Substitution Gone Awry

Here is my problem:

I'm trying to edit an XML file going line by line. I am editing each fault title element I come across (distinguished by <fault-title></fault-title>) to include a unique identifier right before the </fault-title>. My code is below:

    while ($fname = <*.xml>) {      # Skip temp files and template files (marked with xxx in the filename).      if ($fname =~ /tempfile/) {next; } 
if ($fname =~ /XXX/) {next; }
if ($fname =~ /Copy/) {next; }
if ($fname =~ /AUTO.xml/) {next; }

# Open file for reading. The file will be handled like an array of lines so we will be going line by line.
open (INFILE, "$fname") or die "Can't open $fname \n";
@oneline = <INFILE>;
close INFILE;

# Make each file not read-only before editing.
chmod(0666, $fname) or die "Can't chmod $fname \n";
open (TEMP1, ">$fname") or die "Can't write to $fname \n"; # Always set the fault group number to start at 1. This will ensure that fault groups
# are numbered correctly with respect to each database.
$fg_number = 1; # Array indices start at 0.
$line_num = 0;

# This is a temporary fault title that will be used to update the actual line of code.
$ft_temp = "";
for ( @oneline ) {

# Find a fault-title.
if ($oneline[$line_num] =~ m/(<fault-title>.*?<\/fault-title>)/ ) {
$fault_title = $1;
$ft_temp = $fault_title; # Check to see if this fault-title already has a number.
if ( $ft_temp =~ m/\((\D{1,2})\s{1}(\d+)\)<\/fault-title>$/ ) {
$ft_temp =~ s/\(\D{1,2} \d+\)/\($project_letter $fg_number\)/;
$oneline[$line_num] =~ s/$fault_title/$ft_temp/;
} else {
# This fault does not already have a number.
$ft_temp =~ s/<\/fault-title>$/ \($project_letter $fg_number\)<\/fault-title>/;
$oneline[$line_num] =~ s/$fault_title/$ft_temp/; # or die "Unable to make substitution: $_ \n";
$fg_number += 1;
print TEMP1 $oneline[$line_num];
$line_num += 1;

close TEMP1;

# After closing the file, change the permissions back to read-only.
chmod(0444, $fname);

I'm sorry about some of the odd formatting. I have no idea how to fix it because that's not how it looks in the post editor.

My code works on all of the fault titles that do not have parentheses in the text between the tags (i.e. <fault-title>Test FAILED</fault-title>). My code does not work if the text between the tags does contain parentheses (i.e. <fault-title>Initialization (INIT) FAILED</fault-title>).

Any help is greatly appreciated.


Feb 7, 2008, 1:02 PM

Views: 332
Re: [mechwarrior3] Substitution Gone Awry

Where ever you do the substitution, use the \Q option to quote all the non word characters in the string (except $ and @):

$oneline[$line_num] =~ s/\Q$fault_title\E/$ft_temp/;

otherwise the parenthesis are getting treated like a capturing group and not literal parenthesis.

New User

Feb 7, 2008, 1:10 PM

Views: 330
Re: [KevinR] Substitution Gone Awry

Ohhh. So that's how those work. Thanks, Kevin. I definitely misunderstood my Perl documentation when reading about s/// and m//. Thanks again. :)