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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to delete an item from a text file 1

Status
Not open for further replies.

jewel464g

Technical User
Jul 18, 2001
198
US
I have a text file called alert2.

if $ip matches any line in alert2 then I want that line to be erased from the file.

this is what I have, but it doesn't work because it isn't a hash. Can someone tell me how to do that??

Thanks,
Jewel




#Delete it from alert2
sub DeleteIt{
$| = 1;
# open file and define a handle for it
open(FILE,">>/root/alert2") || die "Unable to open alert2!\n";

# suck the file into an array
@file = <FILE>;

# use a loop to keep reading the file
# until it reaches the end
foreach $line (@file)
{
if ($line =~ $ip){
delete $line;
}
}
# close file when done
close(FILE);
return;
} When faced with a decision, always ask, 'Which would be the most fun?'
 
Here are the steps to do what you want:
1) open file to read it
2) read file into array
3) close file
4) open file to write to it
5) print lines in array that don't contain the ip
6) close file

The following should do it, but beware that is is untested. Make sure to make a copy of the file before testing.
Code:
#Delete it from alert2
sub DeleteIt{
    $| = 1;
    # open file and define a handle for it
    open(FILE,&quot;/root/alert2&quot;) || die &quot;Unable to open alert2!\n&quot;;

    # suck the file into an array
    @file = <FILE>;
    close(FILE);
    open(FILE,&quot;>/root/alert2&quot;) || die &quot;Unable to open alert2 \n&quot;;
    # print the file without $ip
    foreach $line (@file) {
        unless ($line =~ $ip){
            print FILE $line;
        }
    }
    # close file when done
    close(FILE);
    return;
}
 
Good idea to make a copy because that deleted everything in alert2. And it didn't return from the subroutine. Because it didn't perform the last operation. I'm not sure what's wrong. The logic looks correct to me. I'll post the entire program in case it's something I've done wrong. Also, I'm on a linux platform.

Thanks,
Jewel

#!/usr/bin/perl -w

use FileHandle;
use File::Tail 0.98;


#Delete it from alert2
sub DeleteIt{
$| = 1;
# open file and define a handle for it
open(FILE,&quot;/root/alert2&quot;) || die &quot;Unable to open alert2!\n&quot;;

# suck the file into an array
@file = <FILE>;
close(FILE);
open(FILE,&quot;>/root/alert2&quot;) || die &quot;Unable to open alert2 \n&quot;;
# print the file without $ip
foreach $line (@file) {
unless ($line =~ $ip){
print FILE $line;
}
}
# close file when done
close(FILE);
return;
}



#request ip to unblock
print &quot;Please enter the IP to be unblocked: &quot;;
my $ip = <STDIN>;



#open the file for writing, append to whatever data may be there
open (FILE2, &quot;>>/root/Coolips&quot;) || die &quot;Unable to open file!\n&quot;;


autoflush FILE2 1;
$|=1;
print FILE2 $ip;
print FILE2 &quot;\n&quot;;
close(FILE2);


DeleteIt($ip);
'ipdrop $ip off';
$SIG{CHLD} = 'IGNORE';
When faced with a decision, always ask, 'Which would be the most fun?'
 
At the end of your code:

DeleteIt($ip);
'ipdrop $ip off'; <- Is this a typo?
$SIG{CHLD} = 'IGNORE';
 
A couple of things to be aware of:
my $ip = <STDIN>;
$ip will also hold a newline character at the end of the string. You can get rid of it with chomp $ip;. Also, when you:
@file = <FILE>;
each element of @file will also contain a newline character at the end. You can get rid of them with chomp @file;. However your comparison:
($line =~ $ip)
should still work.

When you pass an argument to a subroutine you access it through the special array @_. In your case it doesn't matter since $ip can be accessed anywhere within the namespace. However the proper way to utilize the passed variable would be with $_[0].

Besides not going and looking up why you are using use File::Tail 0.98; and not knowing what $SIG{CHLD} = 'IGNORE'; is used for, the script should work.

 
No 'ipdrop $ip off'; isn't a typo. That's a command to unblock ips, that needs to be run on the command line. I use this in another program so I know it works.

use File::Tail 0.98; was accidentally included in the program since I'm reusing most of another program that I have. It's not being used, so it shouldn't affect anything.

$SIG{CHLD} = 'IGNORE'; is used to clean up all the defunct processes that are spawned when you run a command at the command line from within a program. I was having this problem with another program and this worked beautifully to fix the prob.


What I don't understand is why this part of the code is deleting the whole file instead on the specified ip.


open(FILE,&quot;>/root/alert2&quot;) || die &quot;Unable to open alert2 \n&quot;;
# print the file without $ip
foreach $line (@file) {
unless ($line =~ $ip){
print FILE $line;
}
}
# close file when done
close(FILE);



When faced with a decision, always ask, 'Which would be the most fun?'
 
Just out of curiosity try replacing =~, with eq.

open(FILE,&quot;>/root/alert2&quot;) || die &quot;Unable to open alert2 \n&quot;;
# print the file without $ip
foreach $line (@file) {
unless ($line eq $ip){
print FILE $line;
}
}
 
Forgot a couple of items here.
First check to make sure $ip is not empty, then chomp $line.
I'm assuming your file looks like:
IP_one
IP_two
IP_three
etc
If it looks like:
somedata|somedata|IP|moredata,
In this case &quot;eq&quot; won't work unless you split the fields so you would be right to use =~. With an ip address this will probably work.
Example why =~ doesnt do exact comparison:
$ip = 36;
if($lookfor =~ $ip)
{
print &quot;True&quot;;
}
$lookfor = 100 # returns false
$lookfor = 1136 # returns true
$lookfor = 36105 # returns true

So with this in mind and if you have more in $line than just the IP, you may just need chomp($line).

unless($ip eq &quot;&quot;)
{
open(FILE,&quot;>/root/alert2&quot;) || die &quot;Unable to open alert2 \n&quot;;
# print the file without $ip
foreach $line(@file) {
chomp($line);
unless ($line =~ $ip){
print FILE &quot;$line\n&quot;;
}
}
close(FILE);
}
Sometimes my 2 cents is only worth 1 cent.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top