Reputation: 25
Below is my input file as well as acts my output file too. Need assistance to read and write in the input file. (PS: Input and output is same file)
TS_dunit_ PDX_VER_6
TS_test1_par PDX_VER_0
my code look likes below;
#!/usr/perl/5.14.1
use Getopt::Long;
use strict;
use warnings;
my $file;
GetOptions(
"iofile=s" => \$file
);
if (not defined $file){
print "Please specify input_output (iofile) file\n";
exit;
}
open (my $fh, "$file") or die "Can't open the file $file: ";
open (my $fh1, ">>$file") or die "Can't open the file $file: ";
while (<$fh>){
chomp $_;
next if ($_ !~ /S+/);
$_ =~ /(\S+)\s+(\S+)/;
my $first_underscore =index ($1, '_');
my $dev = substr ($1, $first_underscore + 1,
rindex ($1, '_') - $first_underscore - 1);
my $tag = $2;
my $cat_path = "/testdata/17.26.6/$dev/sd/$tag";
my $arc_path = "archive/$dev/sd/$tag";
if (-d $cat_path){
print $fh1 "$dev $tag IN_CAD\n";
}elsif (-d $arc_path){
print $fh1 "$dev $tag IN_ARCHIVE\n";
}else{
print $fh1 "NA\n";
}
}
print "Done! File been append.\n";
Above code gives output as
TS_dunit_ PDX_VER_6
TS_test1_par PDX_VER_0
IN_CAD
IN_CAD
need help if anyway i can make the output as below instead.
TS_dunit_ PDX_VER_6 IN_CAD
TS_test1_par PDX_VER_0 IN_CAD
Upvotes: 2
Views: 1147
Reputation: 66883
One cannot append to a line in a file without overwriting the rest of the file. A file is a sequence of bytes and we can't "insert" new ones, only overwrite the existing ones (or add more by extending the file). See this post for more detail, for instance.
Instead, write out a new file and then rename it to the original. This does change the inode number; if you need to keep it see the end. The code simplifies the index
+substr
part, by regex.
use warnings;
use strict;
use feature 'say';
use File::Copy qw(mv);
# ... code from the question
open my $fh, '<', $file or die "Can't open $file:$!";
open my $fh_out, '>', $outfile or die "Can't open $outfile:$!";
while (<$fh>)
{
next if not /\S/;
chomp;
my ($dev, $tag) = /.*?_(.*)_\s+(.*)/;
my $cat_path = "/testdata/17.26.6/$dev/sd/$tag";
my $arc_path = "archive/$dev/sd/$tag";
if (-d $cat_path) {
say $fh_out "$_ IN_CAD";
}
elsif (-d $arc_path) {
say $fh_out "$_ IN_ARCHIVE";
}
else {
say $fh_out "NA";
}
}
close $fh;
close $fh_out;
# Changes inode number. See text for comment
move($fh_out, $fh) or die "Can't move $fh_out to $fh: $!";
The regex matches up to the first _
, since ?
makes .*?
non-greedy (it stops at first _
). Then it captures everything until the last _
since .*
is greedy, matching everything until the very last _
. This is what the code in the question does, by using rindex
. Then it captures all after tabs/spaces.
The current line is then printed appended, as in the question, to the output file. Since the output file is temporary its name should be built using File::Temp. Then the file is renamed using File::Copy.
This changes the inode number. If that matters, one way to keep the inode number is as follows. After the output file has been written out open the original file for writing, what will clobber it. Then read from the output file and write to the original file. The content gets copied, to the same inode. Remove the output file when done. See more detail in the post linked in the beginning.
Upvotes: 1