Operating System - HP-UX
1825756 Members
2389 Online
109687 Solutions
New Discussion

Perl+deletion of multiple lines in a file

 
Alain Yoshida
Regular Advisor

Perl+deletion of multiple lines in a file

Hi

Scenario
========
I have a file with the word root appearing randomly in it. Ie on line 7 , 13 , 27 etc.
Id like to delete the line containing "root" and 4 lines above it and 2 lines below it (in a script). Any ideas? If Perl can do it?
thks
3 REPLIES 3
Dennis Handly
Acclaimed Contributor

Re: Perl+deletion of multiple lines in a file

For ex(1) you can do:
ex </root/-4,/root/+2d
wq
EOF

Unfortunately I don't know how to repeat that delete.

With awk, you can save the last 4 lines and and if you find "root", delete those, the current and the next two.
If not, you can write the oldest, and reread.
Hein van den Heuvel
Honored Contributor

Re: Perl+deletion of multiple lines in a file

For problems like those I like to set up a little circular 'lag buffer' using a MOD function on the line number.
Store the lines as $line[$. % 10]
Here I used 10, but any number larger then the look-back range will do.

Now loop through the data, filling the buffer with the current line but deciding whether to print (or modify or whatever) 'lag' lines back.

In your example.
Let's create test data first:

# perl -le "for (1..40) { $_ = q(root) unless $_%11; print }" > test.txt
# cat test.txt

The script

# cat test.pl
while (<>) {
$line[$. % 10] = $_;
$skip = 7 if /root/;
print $line[($. - 4) % 10] unless ($skip-- > 0 or $.<5);
}
# deal with rest of lines in buffer.
for ($.+1 .. $.+4) {
print $line[($_ - 4) % 10] unless $skip-- > 0;
}

Now execute:

# perl test.pl test.txt

This will work for any size input file, at only 10 (or less) records are ever remembered.
An alternative is to suck in all lines, mark the special ones, and print all that are not marked. But now you need enough memory to hold all lines.

# cat test.pl
while (<>) {
$line[$.] = $_;
if (/root/) {
delete $line[$_] for ($.-4 .. $.);
<>;
<>;
}
}
print @line;

Enjoy,
Hein







Dennis Handly
Acclaimed Contributor

Re: Perl+deletion of multiple lines in a file

Here is the awk solution:
awk '
BEGIN {
getline save[NR%4] # assume 4
getline save[NR%4]
getline save[NR%4]
getline save[NR%4]
}
/root/ {
getline # assume 2 to skip
getline
if (getline save[NR%4] != 1) {
exit
}
last=NR
if (getline save[(last+1)%4] != 1) {
print save[(last) % 4]
exit
}
last=NR
if (getline save[(last+1)%4] != 1) {
print save[(last-1) % 4]
print save[(last) % 4]
exit
}
last=NR
if (getline save[(last+1)%4] != 1) {
print save[(last-2) % 4]
print save[(last-1) % 4]
print save[(last) % 4]
exit
}
next
}
{
print save[NR % 4]
save[NR % 4] = $0
}
END {
for (i = NR-(4-1); i <= NR; ++i)
print save[(i) % 4]
} ' file