R
Riad KACED
Dear Perl Fellows,
I'm trying to Find and Replace a pattern with in-place edit.
I have opened the file using the Tie::File module as advised in
perlfaq5.
My regular expression is quite simple :
s/\b$find\b/$replace/g, i.e global substitution of word anchored
pattern.
I found that the above fails whenever the pattern shows up more than
once in a line.
The Segmentation fault goes off by removing either the global modifier
or the word anchors. This is not what I want though. I spent entire
morning trying to figure it out but I have failed I'm afraid :-(
Anyway, my script is:
#!/usr/local/bin/perl -w
use strict;
use Tie::File;
use File::Copy;
my $spectreModelFile=shift;
my $spectreSubcktName=shift;
my @newpinNames=@ARGV;
my @spectreSubcktpinNames = getSpectreSubcktTerminals
($spectreModelFile,$spectreSubcktName);
my $newpinNamesLngth = @newpinNames;
my $spectreSubcktpinNamesLngth = @spectreSubcktpinNames;
unless ($newpinNamesLngth == $spectreSubcktpinNamesLngth)
{
die "Port Number mismatch: Given=$newpinNamesLngth, Needed=
$spectreSubcktpinNamesLngth\n" ;
}
copy($spectreModelFile,"$spectreModelFile.bak");
for (my $i=0; $i<$newpinNamesLngth ; $i++)
{
my $find=$spectreSubcktpinNames[$i];
my $replace=$newpinNames[$i];
print("Step # $i : find=$find, replace=$replace\n");
unless($find eq $replace)
{
findAndReplace($spectreModelFile,$find,$replace);
}
}
#-----------------------------------------------------------
# subroutine : findAndReplace
#-----------------------------------------------------------
sub findAndReplace
{
my ($inputFile,$find,$replace)=@_;
print("Attempting to replace $find by $replace ... ");
tie my @inputFile,'Tie::File',$inputFile or die "$inputFile : $!\n";
for (@inputFile)
{
s/\b$find\b/$replace/g; # This comes with a Segmentation fault
#s/\b$find\b/$replace/; # This is fine but it is not why I want
#s/$find/$replace/g; # This is fine but it is not why I want
}
untie @inputFile;
print("OK\n");
}
#-----------------------------------------------------------
# subroutine : getSpectreSubcktTerminals
#-----------------------------------------------------------
sub getSpectreSubcktTerminals
{
my ($spectreModelFile,$spectreSubcktName)=@_;
open(SPECTREMODELFILE,"< $spectreModelFile") or die "cannot read-
open $spectreModelFile : $!";
my @subcktTerminals;
while (my $line=<SPECTREMODELFILE>)
{
# Skip the commented lines. Blank lines : m/^\s*$/ are left
next if ($line =~ m/^\s*$/); # Skip blank lines
next if ($line =~ m/^s*\*/); # Skip commented lines, starting
with a leading Opt WS + '*'
next if ($line =~ m/^s*\/\//);# Skip commented lines, starting
with a leading Opt WS + '//'
# subckt and2 A B Vdd Vss Y
if ($line =~ m/^\s*subckt\s+\b$spectreSubcktName\b((?:\s+\w+)+)/)
{
my $subcktTerminals=$1;
$subcktTerminals =~ s/^\s+//;
@subcktTerminals=split(/\s+/,$subcktTerminals);
last;
}
}
close(SPECTREMODELFILE);
@subcktTerminals;
}
# EOF script
The script could be run as following :
myScript.pl myInFile mySubckt p1 p2 p3 p4 p5
myInFile is a text file (a Spectre subcircuit to be more precise):
// File starts here
subckt mySubckt a1 a12 vdd vss out
m0 vdd a1 2 vss myNmos l=1u w=10u
m1 vss a12 out vss myPmos l=1u w=10u
m2 2 a12 out out myPmos l=1u w=10u
ends mySubckt
// file ends here
FYI:
Perl Version: v5.8.0 (5.008)
OS = Suse Linux ES 9, Patch 3, kernel release 2.6.5-7.287.3.PTF.
363939.1-smp
Thanks in advance for your help !
regards,
Riad.
I'm trying to Find and Replace a pattern with in-place edit.
I have opened the file using the Tie::File module as advised in
perlfaq5.
My regular expression is quite simple :
s/\b$find\b/$replace/g, i.e global substitution of word anchored
pattern.
I found that the above fails whenever the pattern shows up more than
once in a line.
The Segmentation fault goes off by removing either the global modifier
or the word anchors. This is not what I want though. I spent entire
morning trying to figure it out but I have failed I'm afraid :-(
Anyway, my script is:
#!/usr/local/bin/perl -w
use strict;
use Tie::File;
use File::Copy;
my $spectreModelFile=shift;
my $spectreSubcktName=shift;
my @newpinNames=@ARGV;
my @spectreSubcktpinNames = getSpectreSubcktTerminals
($spectreModelFile,$spectreSubcktName);
my $newpinNamesLngth = @newpinNames;
my $spectreSubcktpinNamesLngth = @spectreSubcktpinNames;
unless ($newpinNamesLngth == $spectreSubcktpinNamesLngth)
{
die "Port Number mismatch: Given=$newpinNamesLngth, Needed=
$spectreSubcktpinNamesLngth\n" ;
}
copy($spectreModelFile,"$spectreModelFile.bak");
for (my $i=0; $i<$newpinNamesLngth ; $i++)
{
my $find=$spectreSubcktpinNames[$i];
my $replace=$newpinNames[$i];
print("Step # $i : find=$find, replace=$replace\n");
unless($find eq $replace)
{
findAndReplace($spectreModelFile,$find,$replace);
}
}
#-----------------------------------------------------------
# subroutine : findAndReplace
#-----------------------------------------------------------
sub findAndReplace
{
my ($inputFile,$find,$replace)=@_;
print("Attempting to replace $find by $replace ... ");
tie my @inputFile,'Tie::File',$inputFile or die "$inputFile : $!\n";
for (@inputFile)
{
s/\b$find\b/$replace/g; # This comes with a Segmentation fault
#s/\b$find\b/$replace/; # This is fine but it is not why I want
#s/$find/$replace/g; # This is fine but it is not why I want
}
untie @inputFile;
print("OK\n");
}
#-----------------------------------------------------------
# subroutine : getSpectreSubcktTerminals
#-----------------------------------------------------------
sub getSpectreSubcktTerminals
{
my ($spectreModelFile,$spectreSubcktName)=@_;
open(SPECTREMODELFILE,"< $spectreModelFile") or die "cannot read-
open $spectreModelFile : $!";
my @subcktTerminals;
while (my $line=<SPECTREMODELFILE>)
{
# Skip the commented lines. Blank lines : m/^\s*$/ are left
next if ($line =~ m/^\s*$/); # Skip blank lines
next if ($line =~ m/^s*\*/); # Skip commented lines, starting
with a leading Opt WS + '*'
next if ($line =~ m/^s*\/\//);# Skip commented lines, starting
with a leading Opt WS + '//'
# subckt and2 A B Vdd Vss Y
if ($line =~ m/^\s*subckt\s+\b$spectreSubcktName\b((?:\s+\w+)+)/)
{
my $subcktTerminals=$1;
$subcktTerminals =~ s/^\s+//;
@subcktTerminals=split(/\s+/,$subcktTerminals);
last;
}
}
close(SPECTREMODELFILE);
@subcktTerminals;
}
# EOF script
The script could be run as following :
myScript.pl myInFile mySubckt p1 p2 p3 p4 p5
myInFile is a text file (a Spectre subcircuit to be more precise):
// File starts here
subckt mySubckt a1 a12 vdd vss out
m0 vdd a1 2 vss myNmos l=1u w=10u
m1 vss a12 out vss myPmos l=1u w=10u
m2 2 a12 out out myPmos l=1u w=10u
ends mySubckt
// file ends here
FYI:
Perl Version: v5.8.0 (5.008)
OS = Suse Linux ES 9, Patch 3, kernel release 2.6.5-7.287.3.PTF.
363939.1-smp
Thanks in advance for your help !
regards,
Riad.