Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Putting a line in a specific place in a file

Reply
Thread Tools

Putting a line in a specific place in a file

 
 
samasama
Guest
Posts: n/a
 
      11-01-2006
Hi... I need to place a line in a specific part of the file. I don't
really know where to begin. Aside from feeding the file contents into
an array?


[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4
exclude=httpd

I need to find the [base] entry and then put the exclude= below the
gpgkey= line.

Any help is vastly appreciated. Any docs or turtorials about writing a
parser would help too.

Thanks

--
samasama

 
Reply With Quote
 
 
 
 
anno4000@radom.zrz.tu-berlin.de
Guest
Posts: n/a
 
      11-01-2006
samasama <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Hi... I need to place a line in a specific part of the file. I don't
> really know where to begin. Aside from feeding the file contents into
> an array?


That's a faq. Find it through "perldoc -q 'line in a file'". The
(terse) answer is to tie an array to the file so it *looks* like the
contents were fed into the array. The use pattern matching (and
possibly List::Util::first) to locate your place and add a line
after it.

Anno

> [base]
> name=CentOS-$releasever - Base
> mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
> #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
> gpgcheck=1
> gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4
> exclude=httpd
>
> I need to find the [base] entry and then put the exclude= below the
> gpgkey= line.
>
> Any help is vastly appreciated. Any docs or turtorials about writing a
> parser would help too.
>
> Thanks
>
> --
> samasama
>



 
Reply With Quote
 
 
 
 
samasama
Guest
Posts: n/a
 
      11-01-2006

>
> Looks like you are trying to edit an INI file. If so, have you looked
> at CPAN for INI related modules? such as Config::INI::Simple.
>
> --


Config file yeah... I need to learn how to do this by hand though.
The only part I'm stuck at is determing what line number my first
regex is on and how many lines
down to my next regex.
Something like:
use strict;
use Fcntl;

my $file = "/etc/yum.repos.d/CentOS-Base.repo";
sysopen( REPO_FILE, $file, O_RDONLY )
|| die "Can't open web03 passwd file!: $!\n";

my @file = <REPO_FILE>;

my ( $number1, $number2 );
foreach my $line (@file) {
if ( $line =~ /\[base\]/i ) {
print "Found $line on line $..\n";
}
}

Except $. gives me the total number of lines, not the line number $line
is on.

I think I'm going in the right direction? : )

--
samasama

 
Reply With Quote
 
samasama
Guest
Posts: n/a
 
      11-01-2006

> That would be because you are not looping through the file when you
> print $. . You've slurped the whole file into @file and are looping
> through @file. It's no surprise that $. is equal to the last line
> number of the input file.
>
> You may want to loop through the file handle vs looping on @file. Or
> loop through @file using
> for my $i ( 0 .. $#file ) {
> if ( $line =~ ...
> }
> --
>


Thanks, that does make sense : )
I did a while (<FH>) and am able to find the line it's line number, but
how would I go about finding the first instance of $line =~ /gpgkey/
below it? And get the line number.

Thanks

--
samasama

 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      11-01-2006
samasama <(E-Mail Removed)> wrote:

> I did a while (<FH>) and am able to find the line it's line number, but
> how would I go about finding the first instance of $line =~ /gpgkey/
> below it? And get the line number.



while ( <FH> ) { # skip some lines
last if $. == $magic_line_number;
}

while ( <FH> ) { # start search "below it"
print "found on line $.\n" if /gpgkey/;
}


--
Tad McClellan SGML consulting
http://www.velocityreviews.com/forums/(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
John W. Krahn
Guest
Posts: n/a
 
      11-02-2006
Tad McClellan wrote:
> samasama <(E-Mail Removed)> wrote:
>
>>I did a while (<FH>) and am able to find the line it's line number, but
>>how would I go about finding the first instance of $line =~ /gpgkey/
>>below it? And get the line number.

>
>
> while ( <FH> ) { # skip some lines
> last if $. == $magic_line_number;
> }
>
> while ( <FH> ) { # start search "below it"
> print "found on line $.\n" if /gpgkey/;
> }


while ( <FH> ) {
( $. == $magic_line_number .. /gpgkey/ ) =~ /E/
&& print "found on line $.\n";
}



John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
 
Reply With Quote
 
samasama
Guest
Posts: n/a
 
      11-02-2006

> while ( <FH> ) {
> ( $. == $magic_line_number .. /gpgkey/ ) =~ /E/
> && print "found on line $.\n";
> }
>
>


I like that little number there... and it works too.
Now I need to figure it out : )

$. == the line matched earlier loop until gpgkey ?

--
samasama

 
Reply With Quote
 
samasama
Guest
Posts: n/a
 
      11-06-2006

>
> I like that little number there... and it works too.
> Now I need to figure it out : )
>
> $. == the line matched earlier loop until gpgkey ?
>
> --
> samasama


I still don't really understand that line, but here's what I got...

use strict;
use Fcntl;

my $file = "CentOS-Base.repo";
sysopen( REPO_FILE, $file, O_RDWR )
|| die "Can't open repo file !: $!\n";

my $base_line;
my $gpg_line;
while (<REPO_FILE>) {
chomp $_;
if ( $_ =~ /\[base\]/i ) {
$base_line = $.;
print "Found $_ on line $base_line\n";

}

if ( ( $. == $base_line .. /gpgkey\=/i ) =~ /E/ ) {
print "Found $_ on line $.\n";
$gpg_line = $.;
print REPO_FILE "\nfoo\n";
}

This finds the lines correctly but if I try to print after $gpg_line,
the line below gets fubar.
I know I could use Tie::File, but i really want to understand what's
going on and how to insert my line after $gpg_line correctly.

--
samasama

 
Reply With Quote
 
anno4000@radom.zrz.tu-berlin.de
Guest
Posts: n/a
 
      11-06-2006
samasama <(E-Mail Removed)> wrote in comp.lang.perl.misc:

[positioning a file handle]

> This finds the lines correctly but if I try to print after $gpg_line,
> the line below gets fubar.
> I know I could use Tie::File, but i really want to understand what's
> going on and how to insert my line after $gpg_line correctly.


Well, you can't.

A file is really a sequence of bytes, no more, no less. You can
append to the end of a file, but writing anywhere else implies
overwriting what's already there.

That's what happened to the "line below". It was partially overwritten
by the new data you wrote.

Editors and other tools that work on text files make it look like
a file was a sequence of lines that new lines could be inserted in.
That's software that makes it look like that. There is no insert
operation on the file level.

[side note]

Pity we can no longer refer to the FAQ for this question.

Perlfaq5 "How do I change one line in a file/delete a line..." used to
explain this problem in detail. These days it just refers to Tie::File,
another tool that makes files look like a sequence (a Perl array) of lines.

Anno
 
Reply With Quote
 
samasama
Guest
Posts: n/a
 
      11-06-2006

http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de wrote:
> samasama <(E-Mail Removed)> wrote in comp.lang.perl.misc:
>
> [positioning a file handle]
>
> > This finds the lines correctly but if I try to print after $gpg_line,
> > the line below gets fubar.
> > I know I could use Tie::File, but i really want to understand what's
> > going on and how to insert my line after $gpg_line correctly.

>
> Well, you can't.
>
> A file is really a sequence of bytes, no more, no less. You can
> append to the end of a file, but writing anywhere else implies
> overwriting what's already there.
>


Duh... Yeah I feel dumb : P I don't know why I thought I could just
print the line.

>
> Pity we can no longer refer to the FAQ for this question.
>
> Perlfaq5 "How do I change one line in a file/delete a line..." used to
> explain this problem in detail. These days it just refers to Tie::File,
> another tool that makes files look like a sequence (a Perl array) of lines.


Yeah, Tie::File is great, but I needed to learn the steps in writing my
own parser, for future projects.

While, I've figured out what I needed to do and I'll paste the last of
the code below... I still don't understand what if ( ( $. == $base_line
... /gpgkey\=/i ) =~ /E/ ) { translates too.
It looks like $. == $base_line go down using .. until we hit gpgkey,
and I have no idea what the /E/ means. I'd really like to understand
that.

Code:

use strict;
use Fcntl;
use File::Copy;

my $file = "CentOS-Base.repo";
sysopen( REPO_FILE, $file, O_RDWR )
|| die "Can't open repo file !: $!\n";

my ( $base_line, $gpg_line, $found_exclude, $excluded, $exclude_line,
$package_excluded );
my $package = $ARGV[0];

print "$package\n";
while (<REPO_FILE>) {
chomp $_;
if ( $_ =~ /\[base\]/i ) {
$base_line = $.;
print "Found $_ on line $base_line\n";

}

if ( ( $. == $base_line .. /gpgkey\=/i ) =~ /E/ ) {
print "Found $_ on line $.\n";
$gpg_line = $.;
}
if ( ( $. == $gpg_line .. /exclude\=.*/i ) =~ /E/ ) {
$exclude_line = $.;
$found_exclude = 1;
print "Found exclude $_ on line $.\n";
$package_excluded = 1 if ($_ =~ m/.*$package.*/);

$excluded = $_;

}
}

# reopen (maybe seek() would be better? )
sysopen( REPO_FILE, $file, O_RDWR )
|| die "Can't open repo file !: $!\n";

sysopen( TEMP_REPO_FILE, "/tmp/repo.XXX", O_CREAT | O_WRONLY )
|| die "Can't create temporary shadow file: $!\n";

while (<REPO_FILE>) {
if ($found_exclude && !$package_excluded) {
if ( $. == $exclude_line ) {
chomp $_;
$_ =~ s/$_/$_ $package\n/;
}
}
else {
if ( $. == $gpg_line ) {
print TEMP_REPO_FILE "exclude\=$package\n" unless
$found_exclude;
}
}
print TEMP_REPO_FILE $_;
}

close TEMP_REPO_FILE;
close REPO_FILE;
copy( "/tmp/repo.XXX", $file );
unlink("/tmp/repo.XXX");

Thanks

--
samasama

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
XML parsing problem finding a specific element in a specific place mazdotnet ASP .Net 2 10-02-2009 10:07 AM
Read a file line by line and write each line to a file based on the5th byte scad C++ 23 05-17-2009 06:11 PM
Putting a line from a text file into a variable, then moving to nextline Vernon Wenberg III Python 4 10-07-2007 05:40 PM
Read a file line by line with a maximum number of characters per line Hugo Java 10 10-18-2004 11:42 AM
Difference between putting code in constructor and putting code in static{} Saurabh Java 6 05-30-2004 02:44 PM



Advertisments