Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Removing part of string from a fixed position ? 3

Status
Not open for further replies.

dirtyholmes

Programmer
Mar 17, 2004
43
AU
If I have a file containing data with rows of numbers as such. How can you sweep through the file and elequantly check and remove (if they exist) the numbers 2233 or 1435, if they appear at the fixed position of 47-50
eg
Before
21086600000193 592843830 2003121323270022335675762
21086600000193 592843830 2003121410190014355558355

After
21086600000193 592843830 200312132327005675762
21086600000193 592843830 200312141019005558355

I have come up with the following but im not sure how to remove the offending numbers from the line. Can anyone post a suggestion.

open MY_FH, "<mytext.txt" or die "$!";

while (<MY_FH>)
{

my $pos = 47;
my $pidx;
my $fidx;
$num;

$pidx = index $_, "2233",47; # Start looking at position 47 of the file
$fidx = index $_, "1435",47;

if(($pidx || fidx) == $pos)
{
#NEED TO REMOVE 2233 or 1435 here
}
}
 
Code:
while (<DATA>) {
    if ((substr($_, 47,4) eq "2233") ||
        (substr($_, 47,4) eq "1435")) {
        $_ = substr($_, 0, 47) . substr($_, 51)
    }
    print;
}

__DATA__
21086600000193  592843830        2003121323270022335675762
21086600000193  592843830        2003121410190014355558355

Output:
21086600000193  592843830        200312132327005675762
21086600000193  592843830        200312141019005558355
 
Another way :
Code:
while (<MY_FH>) {
   s/(?<=^.{47})2233|1435//;
   print;
}


Jean Pierre.
 
Here's another way which is maybe a little nicer than my last solution, as it lets you set everything you need outside the loop, and would also allow search strings of different lengths. Output is same as before on same data.

Code:
my @lookfor = qw(1435 2233);
my $searchpos = 47;

while (my $line = <DATA>) {
    my $found = 0;
    for (my $i=0; $i < @lookfor && !$found; $i++) {
        my $len = length($lookfor[$i]);
        my $x = substr($line, $searchpos, $len);
        if ($x eq $lookfor[$i]) {
            $line = substr($line, 0, $searchpos) . 
                    substr($line, $searchpos + $len);
            $found = 1;
        }
    }
    print $line;
}
 
Very ingenious, Jean Pierre. I'll certainly never beat that for concision, anyway. Have a star.
 
heh, anyone guess which on executes faster? If it's a repeat job or time critical, it'd be worth your time, I think.

An you may need to surround your alternation with some (?:grouping). Concatenation has a higher precedence than alternation, so the look-behind position is likely tied to the the first and has no effect on the second. But I haven't tested.

________________________________________
Andrew - Perl Monkey
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top