Re: Opening a file for reading or writing (was: Newbie)
by OeufMayo (Curate) on Mar 18, 2001 at 01:56 UTC
|
If the only thing you want to edit in your height.txt file, you aim for Laziness and go for the following one-liner:
perl -pi.bak -e "s/'/\t/" height.txt # Win32
perl -pi.bak -e 's/\x27/\t/' height.txt # *nix
But, as I'm typing this one, I realize there's a big flaw in you scheme: What if the Name of Person1 has a single quote in it? Maybe one of the regexen below could do the trick (and fortunately, the previous one made automatically a backup of the file!)
Win32 and *nix versions
perl -pi.bak -e "s/\s(\d+)'(\d+)$/\t$1\t$2/" height.txt
perl -pi.bak -e 's/\s(\d+)\x27(\d+)$/\t$1\t$2/' height.txt
perl -pi.bak -e "@r=split(/\t/);$r[2] =~ s/'/\t/;$_=join(qq'\t',@r)"
+height.txt
perl -pi.bak -e '@r=split(/\t/);$r[2] =~ s/\x27/\t/;$_=join("\t",@r)'
+ height.txt
The first one finds two groups of digit separated by a ' at the end of the string, and replace the ' by a tabulation character.
TMTOWTDI!
<kbd>--
my $OeufMayo = new PerlMonger::Paris({http => 'paris.mongueurs.net'});</kbd> | [reply] [d/l] [select] |
(jeffa) Re: Newbie
by jeffa (Bishop) on Mar 18, 2001 at 01:07 UTC
|
while(<FILE>) {
EEEK! UPDATE!
change your open to
open(FILE, "height.txt") # > means write
Hope you didn't just wipe out your file . . . :O
Yup he did - I should have caught that, I did view
the question BEFORE Corion added code tags - so
<FILE> was not displayed in the while loop.
Sorry.
Jeff
R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
L-L--L-L--L-L--L-L--L-L--L-L--L-L--
| [reply] [d/l] [select] |
|
|
It runs fine now. But it doesn't do anything to the text file I load.
All of my datas stay the same
| [reply] |
Re: Opening a file for reading or writing (was: Newbie)
by Corion (Patriarch) on Mar 18, 2001 at 01:13 UTC
|
The error describes relatively good what went wrong.
FILE was only opened for writing, whereas you want to read from it.
So, go back and recreate the content in that file (it's gone by now) and then open the file for reading :
open FILE, "< $file" or die "Couldn't open $file for reading : $!\n"
+;
while (<FILE>) {
print $_;
};
| [reply] [d/l] |
|
|
I'm a little bit confused.
I want to read the file but also modify the file if it matches with '
so can I just open(FILE, "height.txt");
I tried everything, but it still doesn't do anything.
my data in the text file I load stay the same.
| [reply] |
|
|
Inplace modification of text files is considered harmful. I suggest that you write your output first to a second file and then rename the first file to a backup filename and the second file then to the original filename.
If you are bent on modifying a file in place (which is a bad idea while developing a program), just take a look at the documentation for the open() call :
open(DBASE, '+<$file') # open for update
or die "Can't open '$file' for update: $!";
But I really really really have to recommend that you let your script output the stuff to the console first, and then simply redirect the console output into a new file. This is much much safer, and Perl has the -i command line switch which lets you switch on the in place modification easily. | [reply] [d/l] |
|
|
Try this: perl -i.bak -pe "s/\'/\t/;" somefile.dat
The entire problem can be solved with a one-liner. Using tr or y instead of s might be good in this case because s loses performance due to regex computation. You don't really need a regex here -- you're only replacing one character -- unless, of course, you only want to replace the first one, in which case use s.
Modifying a file, then putting the modified file in place of the original file, is known as modifying the file "in place", which is done using the i switch. The .bak is to make a backup as somefile.dat.bak, so that in case of error, you can recover the original data. Since you are modifying it in place, your while(<FILE>) { ... } loop becomes a while(<>) { ... } loop. To get the modified data to be output back to the file, you need to use a print statement, thus: while(<>) { ... print; } This can be accomplished by using the p switch, which places that around whatever code is given. Finally, the resulting code is so short that it can be one-lined using e, which is "run code from next argument".
See perlman:perlrun and perlman:perlop for more information on perl options and operators.
Drake Wilson
Update: D'oh! Corion had already pointed out -i. Oh well.
| [reply] [d/l] [select] |
Re: Opening a file for reading or writing (was: Newbie)
by how do i know if the string is regular expression (Initiate) on Mar 18, 2001 at 01:49 UTC
|
The '>' in the open call truncates and open's the file for
writing. You want to open it in in update mode ('+<'). This
will open it for reading and writing.
Try this:
#!/usr/local/bin/perl -w
use strict;
use warnings;
open(FILE, "+<height.txt") || die "file can't be opened";
my @file = <FILE>; # Read entire file into array
map{ s/'/\t/g } @file; # substitution on each element
seek(FILE,0,0); # go back to the beginning of the file
truncate(FILE, tell(FILE)) # truncate from here to end of file
print FILE @file; # write back to file
close FILE;
I don't really think you need the truncate() here... but
it's safer. If the size of the data you wind up writing to
the file is smaller then the size of the original file,
the truncate will get rid of that excess data. Which is
not the case here. But it's good habit.
- FrankG | [reply] [d/l] |
Re: Opening a file for reading or writing (was: Newbie)
by enoch (Chaplain) on Mar 18, 2001 at 01:12 UTC
|
Did you check your permissions for opening the file?
Jeremy | [reply] |
|
|
| [reply] |
Re: Opening a file for reading or writing (was: Newbie)
by LiTinOveWeedle (Scribe) on Mar 18, 2001 at 18:35 UTC
|
Here is something wich should work. It litle big but you can cut it.
# --------------------------------------------------------------------
+-----
# read array from file
sub read_file {
my ( $line );
if ( not open(FILE, $file_path) ) {
&logging( "Can't open database file." );
die;
}
if ( $file_lock ) { flock(FILE, 1); }
@file = ();
while ( $line = <FILE> ) {
chomp($line);
push(@file, $line);
}
}
<p>
Now you can do anything you want with array @file.
# --------------------------------------------------------------------
+-----
# write array back to file
sub write_file {
my ( $line );
if ( not open(FILE, ">".$file_path) ) {
&logging( "Can't open database file." );
die;
}
if ( $file_lock ) { flock(FILE, 2); }
foreach $line ( @file ) { print FILE "$line\n"; }
close(FILE);
}
if $file_lock is <> 0 then script will use file locking.
Li Tin O've Weedle
mad Tsort's philosopher | [reply] [d/l] [select] |
|
|
First of all useful error messages should always
preserve whatever information you can get on what went
wrong. In this case that means you shouldn't lose the
filename and contents of $!.
Secondly your file locking makes all of the usual mistakes
and will be subject to all of the regular race conditions.
You need to put your locks around the entire
sequence of actions that should be an atomic unit. There
have been several threads on this before, see Re (tilly) 1: Flock Feedback
for an example.
| [reply] |
Re: Opening a file for reading or writing (was: Newbie)
by Anonymous Monk on Mar 19, 2001 at 06:23 UTC
|
Your opening the file as if you were writing to it.
try:open(FILE, "height.txt") or die "file can't be opened: $!";
or:
open(FILE, "<height.txt") or die "file can't be opened: $!";
notice the difference in the file operator
'>' is for writing to
'<' is for reading from
''(nothing) is default read from
2001-03-19 Edit by Corion : Added CODE tags | [reply] [d/l] [select] |