Re: File editing
by zejames (Hermit) on Sep 28, 2000 at 16:40 UTC
|
Something like this could do what you want:
open SOURCE,"<source.file" or die "Error opening source.file: $!";
open DEST,">dest.file" or die "Error opening dest.file: $!";
while ($line = <SOURCE>)
{
next if ( 1 .. ($line =~ /RE/) );
print DEST $line;
}
And the you can rename dest.file to source.file.
HTH
James
Update: Followed tilly's advices about warnings and errors
| [reply] [d/l] |
|
|
First of all those die statements are very uninformative. At the least you should say the attempted action, the filename, and report the OS error with $!. For something this simple there is no reason to not just read from @ARGV with <>.
If you have ever had to get a broken script with useless error reporting working again at midnight when it turns out that someone (not me!) had been mucking around as root and left permissions wrong on one file in several thousand, you will appreciate why I am a stickler for this!
Secondly you will lose the end of the line with the RE, so you didn't quite answer the problem stated. OTOH I suspect that you did answer the question that really was meant.
| [reply] |
(ar0n) Re: File editing
by ar0n (Priest) on Sep 28, 2000 at 17:28 UTC
|
I'm not sure wether you mean "delete everything until the string 'RE' is encountered" or "delete everything until an RE is encountered."
For simplicity's sake I'll go with the former.
#!/usr/bin/perl -w
use strict;
my $found = 0;
while (<>) {
if ($found or /RE(.*?)/) {
$found = 1;
print;
}
}
I love unix:
[ar0n@zendo perl]$ perl re.pl < INPUT > OUTPUT
[ar0n]
| [reply] [d/l] [select] |
Re: File editing
by Jonathan (Curate) on Sep 28, 2000 at 17:35 UTC
|
Perhaps this would be clear if I posted my current feeble attempt. Basically I just want the remainder of the file after a certain position. Mine does the job, I just wondered if theres a cleaner more elegant way.
#!/usr/local/bin/perl -w
open FH,"+<file_name" or die "go away";
@x = <FH>;
$keep_bit=0;
foreach (@x) {
if (/^RE$/) {
$keep_bit++;
}
if ($keep_bit) {
push(@y,$_);
}
}
seek (FH,0,0);
print FH @y;
truncate(FH, tell(FH));
close FH;
"We are all prompted by the same motives, all deceived by the same fallacies, all animated by hope, obstructed by danger, entangled by desire, and seduced by pleasure."
- Samuel Johnson | [reply] [d/l] |
Re: File editing
by dchetlin (Friar) on Sep 28, 2000 at 23:41 UTC
|
This problem is tailor-made for the flipflop operator.
perl -i.bak -nwe'(/REx/ .. 0) && print'
Of course, that will print the line that matched the REx. What you really want is hard to tell -- whether you want to start with the line after the REx or whether you want the line with the REx on it, and just starting as soon as the end of the REx matches.
perl -i.bak -nwe'(s/.*REx// .. 0) && print'
That will provide option #2 -- you get everything directly following the REx match, including the text on the same line.
perl -i.bak -nwe'print if $match; /REx/ && $match++'
And this one gives you all of the lines immediately following the line where the REx matched.
All of these examples can also be wrapped in while (<>) { ... } instead of used with the command line switches if necessary.
-dlc | [reply] [d/l] [select] |
|
|
Hey! I like this, never crossed my mind to do a one liner. To be honest I don't care whether the RE line is in or out - it's only a theoretical problem (just a small diversion from writing bloody Sybase SB procs)
"We are all prompted by the same motives, all deceived by the same fallacies, all animated by hope, obstructed by danger, entangled by desire, and seduced by pleasure."
- Samuel Johnson
| [reply] |
Re: File editing
by mirod (Canon) on Sep 28, 2000 at 17:44 UTC
|
OK, I'll give it a try:
- If your file fits in memory and you want the rest of the
line after the RE try:
perl -i -e 'undef $/; ($dump, $keep)= split /RE/, <>; print $keep;' file
- Now if you want to keep lines AFTER the RE this should work...
but it does not! Anybody can point my mistake?:
perl -i -p -e '<> until( $ok || m/RE/); $ok=1 ' foo
| [reply] [d/l] [select] |
|
|
You need to set $_ explicitely here.
perl -i -p -e '$_ = <> until $ok || m/RE/; $ok=1' foo
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
|
|
Wow ... peek into my brain as I look at your code above:
- Why would that work? What on earth are you trying to do?
- Oh, I see ... hmm, why doesn't that work? It's bizarre, but it should...
- Ah, duh. The magic diamond operator doesn't automatically assign to $_ -- it's the while magic that does that. So you're comparing the REx against the same $_ the whole time, causing an infinite loop.
Even if you did assign your diamond operator to a variable, you're still going to accidentally let the first line of the file through, because it's already been pulled out by the implicit while (<>) { ... } continue { print } that the -p switch gives you. Basically, using the diamond operator inside of a -p or -n script is going to do strange things. I'd avoid it. See my note further down on a non-confusing way to do this :-)
-dlc
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: File editing
by Jouke (Curate) on Sep 28, 2000 at 16:10 UTC
|
Do you mean deleting everything until you find a RE in the file, or do you mean processing the file with a RE?
I think it merely depends on what exactly you want to do. Is it a big file, or just a few lines? Is it a complex RE you want to process? Be more exact please.
Jouke Visser, Perl 'Adept'
| [reply] |
|
|
deleting everything until the RE is found
"We are all prompted by the same motives, all deceived by the same fallacies, all animated by hope, obstructed by danger, entangled by desire, and seduced by pleasure."
- Samuel Johnson
| [reply] |
RE: File editing
by Anonymous Monk on Sep 29, 2000 at 04:47 UTC
|
I usually do this sort of thing in following manner:
open FH, "<fh.txt" or die "$!\n";
while (<FH>) {
push(@y, $_), next if $flag;
/^RE$/ and push(@y, $_), $flag++;
}
close FH;
This keeps things a bit more efficient, as it
minimalizes the amount of superflous tests --
why continue the extra overhead ( however minimal )
of checking for /^RE$/ after we already know
it's been met?
| [reply] [d/l] |
|
|
Grumble.... I didn't realize I wasn't logged in,
that anonymous post was mine... ah well.
| [reply] |