in line editing

R

roller

Perl Gurus I need some help,

I am currently using a shell script to read in a file of usernames and
then for each matching one in a seperate file change the matching
line. The problem is I do this by grep -v username file1 > file1.temp
and then move file1.temp over file1. What this does is it sticks all
the changes at the bottom. I need to preserve the structure in file1
which is like this:

# Comment
username -soft server:/export/vol00/users:username

Because the comment explains some details of the user below. How can I
use perl to read in a file of usernames then for each match in file1
do an in line edit using

s/server/another_server/

This way I can ensure the comment above each matching line still
explains the line below.

Thanks
 
M

Matija Papec

X-Ftn-To: roller

Because the comment explains some details of the user below. How can I
use perl to read in a file of usernames then for each match in file1
do an in line edit using

s/server/another_server/

This way I can ensure the comment above each matching line still
explains the line below.

This is FAQ, perldoc Tie::File
 
E

Eric Schwartz

Matija Papec said:
X-Ftn-To: roller


This is FAQ, perldoc Tie::File

That's overkill for a problem that can be solved with a simple

perl -pi.bak -e 's/this/that/' file

don't you think? 'perldoc perlrun' for more information on what those
flags do-- and please do run this perldoc, as none of this is magic,
and you might figure out how to save another trip to USENET next time.

-=Eric
 
I

ioneabu

roller said:
Perl Gurus I need some help,

I am currently using a shell script to read in a file of usernames and
then for each matching one in a seperate file change the matching
line. The problem is I do this by grep -v username file1 > file1.temp
and then move file1.temp over file1. What this does is it sticks all
the changes at the bottom. I need to preserve the structure in file1
which is like this:

# Comment
username -soft server:/export/vol00/users:username

Because the comment explains some details of the user below. How can I
use perl to read in a file of usernames then for each match in file1
do an in line edit using

s/server/another_server/

This way I can ensure the comment above each matching line still
explains the line below.

Thanks

I wrote this earlier today and wasn't going to post it because I like
the one line solution better, but here it is anyway:

#!/usr/bin/perl

use warnings;
use strict;

open USERS, './usernames.txt' or die "error";
open IN, './file1.txt' or die "error";
my @file1 = <IN>;
my @usernames = <USERS>;
close IN;
chomp @usernames;
for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}
open OUT, '>./file1.txt' or die "error";
print OUT for @file1;

I tried changing to use scalar file handles and 3 argument open:

#!/usr/bin/perl

use warnings;
use strict;

open my $users, './usernames.txt' or die "error";
open my $in, './file1.txt' or die "error";
my @file1 = <$in>;
my @usernames = <$users>;
close $in;
chomp @usernames;
for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}
open my $out, '>', './file2.txt' or die "error";
print $out for @file1; #problem line

and it unexpectedly prints to STDOUT:

GLOB(0x183522c)GLOB(0x183522c)GLOB(0x183522c)

I was also wondering why I can't write

for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}

as

$file1[$i] =~ s/username/$usernames[$i]/g
for (my $i=0;$usernames[$i];$i++);

Thanks!

wana
 
J

John W. Krahn

I wrote this earlier today and wasn't going to post it because I like
the one line solution better, but here it is anyway:

#!/usr/bin/perl

use warnings;
use strict;

open USERS, './usernames.txt' or die "error";
open IN, './file1.txt' or die "error";
my @file1 = <IN>;
my @usernames = <USERS>;
close IN;
chomp @usernames;
for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}
open OUT, '>./file1.txt' or die "error";
print OUT for @file1;

I tried changing to use scalar file handles and 3 argument open:

#!/usr/bin/perl

use warnings;
use strict;

open my $users, './usernames.txt' or die "error";
open my $in, './file1.txt' or die "error";

Those are using "3 argument open"? Don't you mean:

open my $users, '<', './usernames.txt' or die "error";
open my $in, '<', './file1.txt' or die "error";

my @file1 = <$in>;
my @usernames = <$users>;
close $in;
chomp @usernames;
for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}
open my $out, '>', './file2.txt' or die "error";
print $out for @file1; #problem line

Unfortunately perl doesn't DWIM in this case. You have to explicitly add the
list after the filehandle:

print $out $_ for @file1;

and it unexpectedly prints to STDOUT:

GLOB(0x183522c)GLOB(0x183522c)GLOB(0x183522c)

I was also wondering why I can't write

for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}

as

$file1[$i] =~ s/username/$usernames[$i]/g
for (my $i=0;$usernames[$i];$i++);

Because the statement modifier 'for' only works with lists. You might be able
to do it with something like this:

$file1[$_] =~ s/username/$usernames[$_]/g for 0 .. $#usernames;



John
 
R

roller

John W. Krahn said:
my @file1 = <$in>;
my @usernames = <$users>;
close $in;
chomp @usernames;
for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}
open my $out, '>', './file2.txt' or die "error";
print $out for @file1; #problem line
Unfortunately perl doesn't DWIM in this case. You have to explicitly add the
list after the filehandle:
print $out $_ for @file1;
and it unexpectedly prints to STDOUT:

GLOB(0x183522c)GLOB(0x183522c)GLOB(0x183522c)

I was also wondering why I can't write

for (my $i=0;$usernames[$i];$i++)
{$file1[$i] =~ s/username/$usernames[$i]/g}

as

$file1[$i] =~ s/username/$usernames[$i]/g
for (my $i=0;$usernames[$i];$i++);
Because the statement modifier 'for' only works with lists. You might be able
to do it with something like this:
$file1[$_] =~ s/username/$usernames[$_]/g for 0 .. $#usernames;
John

Thanks all for the info so far,

To clarify I need to loop through a file say 'names' and for every
occurrence of a username in this file that it finds in file
'auto_home_users' I need to change the line in auto_home_users so that

username -soft server:/export/vol00/users:username

is changed to

username -soft another_server:/export/vol00/users:username

perl -i.bak -p -e would change every line with server to
another_server.
 
M

Matija Papec

X-Ftn-To: Eric Schwartz

Eric Schwartz said:
That's overkill for a problem that can be solved with a simple

perl -pi.bak -e 's/this/that/' file

don't you think?

No, I don't; perhaps OP wants to apply more logic to his line substitution
so oneliner might not be the right thing. On the other hand, this is
actually FAQ,

perldoc -q "change one line"
 
E

Eric Schwartz

To clarify I need to loop through a file say 'names' and for every
occurrence of a username in this file that it finds in file
'auto_home_users' I need to change the line in auto_home_users so that

username -soft server:/export/vol00/users:username

is changed to

username -soft another_server:/export/vol00/users:username

perl -i.bak -p -e would change every line with server to
another_server.

-e just runs any perl code you care to put in it. So all you have to
do is restrict the s/// to lines with username in them:

perl -pi.bak -e 's/server/another_server/ if /^username/' filename

-=Eric
 
E

Eric Schwartz

Matija Papec said:
No, I don't; perhaps OP wants to apply more logic to his line substitution
so oneliner might not be the right thing.

I trust the OP is smart enough to state this if it's the case. The
problem statement, while a bit confused originally, is entirely
amenable to a one-liner, especially as clarified.
On the other hand, this is
actually FAQ,

perldoc -q "change one line"

I've never inveigled against reading the FAQ, and the answer is a
correct one, to be sure, but it's inadequate, if you ask me (nobody
did). The ability to do things easily with perl on the command line
is one of its many strengths, and I think it's unfortunate that the
FAQ ignores it in this case.

How's this for a patch:

--- perlfaq5.pod 2005-02-03 16:37:19.783159978 -0700
+++ /usr/share/perl/5.8.4/pod/perlfaq5.pod 2004-12-11 06:17:59.000000000 -0700
@@ -63,8 +63,7 @@
=head2 How do I change one line in a file/delete a line in a file/insert a line in the middle of a file/append to the beginning of a file?

Use the Tie::File module, which is included in the standard
-distribution since Perl 5.8.0, or check L<perlrun> for
-documentation of the -n and -p switches.
+distribution since Perl 5.8.0.

=head2 How do I count the number of lines in a file?

Comments?

-=Eric
 
M

Matija Papec

X-Ftn-To: Eric Schwartz

Eric Schwartz said:
I've never inveigled against reading the FAQ, and the answer is a
correct one, to be sure, but it's inadequate, if you ask me (nobody
did).

True.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,167
Messages
2,570,910
Members
47,453
Latest member
MadelinePh

Latest Threads

Top