Is there any way with the standard perl libraries to open a file and edit it, without having to close it then open it again? All I know how to do is to either read a file into a string close the file then overwrite the file with a new one; or read and then append to the end of a file.
The following currently works but; I have to open it and close it twice, instead of once:
#!/usr/bin/perl
use warnings; use strict;
use utf8; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8");
use IO::File; use Cwd; my $owd = getcwd()."/"; # OriginalWorkingDirectory
use Text::Tabs qw(expand unexpand);
$Text::Tabs::tabstop = 4; #sets the number of spaces in a tab
opendir (DIR, $owd) || die "$!";
my @files = grep {/(.*)\.(c|cpp|h|java)/} readdir DIR;
foreach my $x (@files){
my $str;
my $fh = new IO::File("+<".$owd.$x);
if (defined $fh){
while (<$fh>){ $str .= $_; }
$str =~ s/( |\t)+\n/\n/mgos;#removes trailing spaces or tabs
$str = expand($str);#convert tabs to spaces
$str =~ s/\/\/(.*?)\n/\/\*$1\*\/\n/mgos;#make all comments multi-line.
#print $fh $str;#this just appends to the file
close $fh;
}
$fh = new IO::File(" >".$owd.$x);
if (defined $fh){
print $fh $str; #this just appends to the file
undef $str; undef $fh; # automatically closes the file
}
}
If you want to open a file for reading and writing, you can put a plus sign before the > or < characters. open DATA, "+>file. txt" or die "Couldn't open file file.
You use open() function to open files. The open() function has three arguments: Filehandle that associates with the file. Mode : you can open a file for reading, writing or appending.
In order to write to the file, it is opened in write mode as shown below: open (FH, '>', “filename. txt”); If the file is existing then it truncates the old content of file with the new content.
FreeKB - Perl (Scripting) Read and write to the same file. Perl's approach to reading and writing to the same file is to store the current file into an array or a temporary file, to update the array or temporary file, and to then replace the original file with the updated array or temporary file.
You already opened the file for reading and writing by opening it with the mode <+
, you're just not doing anything useful with it -- if you wanted to replace the contents of the file instead of writing to the current position (the end of the file) then you should seek
back to the beginning, write what you need to, and then truncate
to make sure that there's nothing left over if you made the file shorter.
But since what you're trying to do is inplace filtering of a file, might I suggest that you use perl's inplace editing extension, instead of doing all of the work yourself?
#!perl
use strict;
use warnings;
use Text::Tabs qw(expand unexpand);
$Text::Tabs::tabstop = 4;
my @files = glob("*.c *.h *.cpp *.java");
{
local $^I = ""; # Enable in-place editing.
local @ARGV = @files; # Set files to operate on.
while (<>) {
s/( |\t)+$//g; # Remove trailing tabs and spaces
$_ = expand($_); # Expand tabs
s{//(.*)$}{/*$1*/}g; # Turn //comments into /*comments*/
print;
}
}
And that's all the code you need -- perl handles the rest. Setting the $^I variable is equivalent to using the -i commandline flag. I made several changes to your code along the way -- use utf8
does nothing for a program with no literal UTF-8 in the source, binmode
ing stdin and stdout does nothing for a program that never uses stdin or stdout, saving the CWD does nothing for a program that never chdir
s. There was no reason to read each file in all at once so I changed it to linewise, and made the regexes less awkward (and incidentally, the /o
regex modifier is good for almost precisely nothing these days, except adding hard-to-find bugs to your code).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With