Perl - How extract file information for logrotate - perl

i have following list of application log files (rotated) and i would get only new lines generated. For do this operation i've think to extract filename, inode and n. of rows from each file, for write it into a temporally file, who i would read each time before my elaboration (I am open to better solutions if you are).
This is my list of files:
root> ls -l
applog_s0.0.log
applog_s0.1.log
applog_s0.2.log
applog_s0.3.log
applog_s1.0.log
applog_s1.1.log
applog_s1.2.log
applog_s1.3.log
applog_s2.0.log
applog_s2.1.log
applog_s2.2.log
applog_s2.3.log
applog_s3.0.log
applog_s3.1.log
applog_s3.2.log
applog_s3.3.log
I can't just read the last log file in order of number, because it may have closed recently and I risk data losing.
This is my draft of script (draft because some instruction return compiled errors):
my $MY_DIR="/usr/cataclust/sharedfolder/logs/";
my %filelist;
# Load file list
foreach my $filename (glob("$MY_DIR/applog_s*.log")) {
my $ino = stat($filename); # Get inode of my file
my $nrows = $. ($filename); # this row doesn't work into script :( it works only by cmd line as perl -ne '}{ print $.' applog_s1.0.log
push( #{ $filelist { filename } }, $filename);
push( #{ $filelist { inode } }, $ino);
push( #{ $filelist { rows } }, $nrows);
}
# Elaborate log
foreach my $filename (glob("$IN_DIR/applog_s*.log")) {
open (FILE, $filename) or die "can't read open $filename";
$/ = "\n\n";
while( <FILE> ) {
my #rows = split /\n\n/;
my $ino = stat($filename);
if( $filename == $filelist{name} && $ino == $filelist{inode} ) {
if( $. < $filelist{rows} ) {
my $rown = $.;
if ($rows[$row] =~ m/\A\d.-\s(\d{8})\s(\d{2}:\d{2}:\d{2})\s-\s(\w+)\s-\s\/Extended Info/) {
if ($rows[$rown] =~ m/WARNING/ || $rows[$rown] =~ m/CRITICAL/ && $rows[$rown] !~ m/INFORMATION/) { # Shows only errors
my ($date, $time, $class, $message ) = $rows[$rown] =~ m/\A\d.-\s(\d{8})\s(\d{2}:\d{2}:\d{2})\s-\s(\w+)\s-\s\/Extended Info\n(\w.*)/;
push #evt, {date => $date, time => $time, classification => $class, information => $message};
}
}
}
}
}
}
This is log example:
0#- 20180403 11:11:11 - ERROR - /Extended Info
Fs Doesn't work...
1#- 20180403 11:12:13 - ERROR - /Extended Info
Fs Doesn't work...
could you help me to clarify?

Related

How to take maximum name from the files with any .txt extension and remove the other contents expect maximum one using perl?

In the below code I tried to filter the maximum name from any files in my path and remove the minimum digit contents from the file using Perl.
Content inside all .txt files in my direcctory:
sv1 12.70% 12.70%
sv2 49.21% 49.21%
sv3 88.89% 88.89%
sv4 92.06% 92.06%
Expectation:
sv4 92.06% 92.06%
code:
use File::Path qw(remove_file);
my $path_output = $output_dir;
find2($path_output);
sub find2{
my ($s1) = #_;
my (#dirs1) = grep { -f && /\.txt$/ } glob $s1.'/*';
print #dirs1;
my ($link1) = sort{
my ($m1)=$a1=~m/\/(sv\d+)$/; my ($n1)=$b1=~/\/(sv\d+)$/; $n1 cmp $m1
} grep{/\/sv\d+$/} #dirs1;
foreach (#dirs1)
{
($_=~m/sv(\d+)$/ && $_ ne $link1)? remove_file($_) : find2($_);
}
}
Error:
"remove_file" is not exported by the File::Path module
print #dirs1 is not printing the matching files.
Edited code:
my $path_output1 = $output_dir;
#print $path_output1;
find2($path_output1);
sub find2{
my ($s1) = #_;
print $s1;
my (#dirs1) = grep { -f && /\.txt$/} glob $s1.'/**/*/*';
#print #dirs1 ;
my ($link1) = sort{
my ($m1)=my $a1=~m/\/(sv\d+)$/; my ($n1)=my $b1=~/\/(sv\d+)$/; $n1 cmp $m1
} grep{/\/sv\d+$/} #dirs1;
#print "****$link1***";
foreach my $file (#dirs1)
{
($file=~m/sv(\d+)$/ && $_ ne $link1)? unlink($file) : find2($file);
#print $file;
}
}
still i had struck with my query.
The module File::Path does not have a function remove_file. Looking at the Changes document, it never had. But Perl has a built-in to delete files: unlink.
Get rid of the use File::Path, you don't need it. Then use unlink in your loop.
foreach my $file (#dirs1)
{
( $file =~ m/sv(\d+)$/ && $_ ne $link1 ) ? unlink($file) : find2($file);
}

Search a list file of files for keywords

I have an array of files. Now I need to cat each file and search for a list of keywords which is in file keywords.txt.
my keywords.txt contains below
AES
3DES
MD5
DES
SHA-1
SHA-256
SHA-512
10.*
http://
www.
#john.com
john.com
and I'm expecting output as below
file jack.txt contains AES:5 (5 line number) http://:55
file new.txt contains 3DES:75 http://:105
Okay Here is my Code
use warnings;
use strict;
open STDOUT, '>>', "my_stdout_file.txt";
my $filename = $ARGV[2];
chomp ($filename);
open my $fh, q[<], shift or die $!;
my %keyword = map { chomp; $_ => 1 } <$fh>;
print "$fh\n";
while ( <> ) {
chomp;
my #words = split;
for ( my $i = 0; $i <= $#words; $i++ ) {
if ( $keyword{ $words[ $i ] } ) {
print "Keyword Found for file:$filename\n";
printf qq[$filename Line: %4d\tWord position: %4d\tKeyword: %s\n],
$., $i, $words[ $i ];
}
}
}
But the problem is its considering all the Arguments and trying to open the files for ARGV[2]. Actually i need to Open only ARGV[0] and ARGV[1]. ARGV[2] i kept for writing in output only.
Appreciate responses.
Thanks.
I think maybe there are multipe keywords in one line of those txt files. So below code for your reference:
my #keywords;
open IN, "keywords.txt";
while(<IN>) {
if(/^(.+)$/) {
push(#keywords, $1);
}
}
close(IN);
my #filelist=glob("*.txt");
foreach my $filename(#filelist) {
if(open my $fh, '<', $filename) {
my $ln=1;
while(my $line = <$fh>) {
foreach my $kw(#keywords) {
if($line=~/$kw/) {
print $filename.':'.$ln.':'.$kw."\n";
}
}
$ln++;
}
}
close($fh);
}
Ok but one thing i noticed here is..
the Keywords
http://
oracle.com
it is matching the whole word, instead it should try to match as part of strings.. Only these keywords.. Others should be searched as per the above.

Modifying Large files line by line using perl script

I am having two huge .csv files one is around 8 GB and other is 3.4 GB file size. I want only few values from each line inside that .csv files.
Its taking huge time to modify the data and copy it into new file.
Could anyone help in modifying the code.So that the modification will be completed in a reasonable time.
Below is the lines of code:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;
require "$ENV{'SAI_HOME'}/bin/utils/Logging.pl";
require "$ENV{'SAI_HOME'}/bin/utils/Utilities.pl";
my $date1 = `date '+%d-%m-%Y_%H-%M-%Ss'`;
chomp($date1);
our $LOGPATH = "$ENV{'SAI_HOME'}/logs/SP6migrationcsv_$date1.log";
my $status = 0;
log_info("Refer $LOGPATH log file for more information");
my $csv = Text::CSV->new( { binary => 1, eol => $/, sep_char => ',' } );
my $file1 = $ARGV[0] or die "Please provide Subscriber and Subscription CSV files on the command line\n";
my $file2 = $ARGV[1] or die "Please provide Subscriber and Subscription CSV files on the command line\n";
my $subscriberFile = "";
my $subscriptionFile = "";
if ( ( grep /SUBSCRIBER/i, $file1 ) && ( grep /SUBSCRIPTION/i, $file2 ) ) {
$subscriberFile = $file1;
$subscriptionFile = $file2;
} elsif ( ( grep /SUBSCRIBER/i, $file2 ) && ( grep /SUBSCRIPTION/i, $file1 ) ) {
$subscriptionFile = $file1;
$subscriberFile = $file2;
} else {
log_error("Invalid CSV files input");
exit -1;
}
my $SP6DIR = `dirname $0`;
chomp $SP6DIR;
$SP6DIR = "${SP6DIR}/SP6";
`mkdir -p $SP6DIR` or checkExit( $?, "Unable to carete $SP6DIR directory" );
my $newSubscriberFile = "Subscriber.csv";
my $newSubscriptionFile = "Subscription.csv";
my $subscriptionimsifile = "$SP6DIR/.IMSI_$newSubscriptionFile";
my $subscriberimsifile = "$SP6DIR/.IMSI_$newSubscriberFile";
$newSubscriberFile = "${SP6DIR}/$newSubscriberFile";
$newSubscriptionFile = "${SP6DIR}/$newSubscriptionFile";
`dos2unix $subscriptionFile $subscriberFile 2>/dev/null`
or checkExit( $?, "Unable to perform dos2unix on input files" );
`cut -d "," -f3 $subscriptionFile > $subscriptionimsifile`
or checkExit( $?, "Failed to get IMSI details from $subscriptionFile" );
`cut -d "," -f1 $subscriberFile > $subscriberimsifile`
or checkExit( $?, "Failed to get IMSI details from $subscriberFile" );
my $isSubscriptionHeaderPresesnt = "false";
my $isSubscriberHeaderPresesnt = "false";
$status = system("head -1 $subscriptionimsifile | grep 'IMSI' >>/dev/null");
if ( $status == 0 ) {
$isSubscriptionHeaderPresesnt = "true";
}
$status = system("head -1 $subscriberimsifile | grep 'IMSI' >>/dev/null");
if ( $status == 0 ) {
$isSubscriberHeaderPresesnt = "true";
}
open( my $subscriptionData, '<:encoding(utf8)', $subscriptionFile )
or die "Could not open '$subscriptionFile' $!\n";
open( NEWSUBSCRIBERDATA, "> $newSubscriberFile" ) or die "Could not open '$newSubscriberFile' $!\n";
open( NEWSUBSCRIPTIONDATA, "> $newSubscriptionFile" ) or die "Could not open '$newSubscriptionFile' $!\n";
if ( "$isSubscriptionHeaderPresesnt" eq "true" ) {
my $subscriptionHeader = <$subscriptionData>;
if ( $csv->parse($subscriptionHeader) ) {
my #subscriptionHeaderFields = $csv->fields();
print NEWSUBSCRIPTIONDATA "\"$subscriptionHeaderFields[0]\",\"$subscriptionHeaderFields[2]\",\"$subscriptionHeaderFields[4]\",\"$subscriptionHeaderFields[5]\",\"$subscriptionHeaderFields[6]\",\"$subscriptionHeaderFields[8]\",\"$subscriptionHeaderFields[13]\",\"$subscriptionHeaderFields[14]\",\"$subscriptionHeaderFields[15]\",\"$subscriptionHeaderFields[16]\",\"$subscriptionHeaderFields[17]\",\"$subscriptionHeaderFields[18]\",\"$subscriptionHeaderFields[25]\",\"$subscriptionHeaderFields[26]\",\"$subscriptionHeaderFields[27]\"\n";
print NEWSUBSCRIBERDATA "\"IMSI\",\"IMEI\",\"MSISDN\",\"$subscriptionHeaderFields[21]\",\"$subscriptionHeaderFields[22]\",\"$subscriptionHeaderFields[12]\",\"$subscriptionHeaderFields[9]\",\"$subscriptionHeaderFields[1]\",\"$subscriptionHeaderFields[0]\"\n";
} else {
log_error("Line could not be parsed: $subscriptionHeader\n");
exit 1;
}
} else {
log_only("No header info in subscription file");
}
if ( "$isSubscriptionHeaderPresesnt" eq "false" && "$isSubscriberHeaderPresesnt" eq "true" ) {
print NEWSUBSCRIBERDATA "\"IMSI\",\"IMEI\",\"MSISDN\",\"CUSTOMER_SEGMENTATION\",\"CUST_SUBCATEGORY\",\"SUBS_TYPE\",\"SUBSCRIPTION_PLAN\",\"CONTRACT_IDREF\",\"SUBSCRIPTION_IDREF\"\n";
} else {
log_only("No header info in subscriber file");
}
my $subscriberHeader = "";
my #subscriptionFields = {};
my #subscriberFields = {};
while ( my $eachSubscriptionLine = <$subscriptionData> ) {
chomp $eachSubscriptionLine;
if ( $csv->parse($eachSubscriptionLine) ) {
#subscriptionFields = $csv->fields();
$status = system("grep \"^[\\\"]*${subscriptionFields[2]}[\\\"]*\\\$\" $subscriberimsifile >> /dev/null");
if ( $status == 0 ) {
my $lastMatchedSubscriberdata = `grep "^[\\\"]*${subscriptionFields[2]}[\\\"]*," $subscriberFile | tail -1`;
chomp $lastMatchedSubscriberdata;
if ( $csv->parse($lastMatchedSubscriberdata) ) {
#subscriberFields = $csv->fields();
if ( "${subscriberFields[0]}" eq "${subscriptionFields[2]}" ) {
#log_only("Updating \"#subscriberFields\" subscriber details from subscription data");
print NEWSUBSCRIBERDATA "\"$subscriberFields[0]\",\"$subscriberFields[1]\",\"$subscriptionFields[2]\",\"$subscriptionFields[21]\",\"$subscriptionFields[22]\",\"$subscriptionFields[12]\",\"$subscriptionFields[9]\",\"$subscriptionFields[1]\",\"$subscriptionFields[0]\"\n";
} else {
log_error("Unable to process #subscriberFields record");
exit -1;
}
} else {
log_error("Line could not be parsed: $lastMatchedSubscriberdata\n");
exit 1;
}
} else {
log_only("Adding new subscriber details from subscription : \"#subscriptionFields\"");
print NEWSUBSCRIBERDATA "\"$subscriptionFields[2]\",,\"$subscriptionFields[3]\",\"$subscriptionFields[21]\",\"$subscriptionFields[22]\",\"$subscriptionFields[12]\",\"$subscriptionFields[9]\",\"$subscriptionFields[1]\",\"$subscriptionFields[0]\"\n";
}
print NEWSUBSCRIPTIONDATA "\"$subscriptionFields[0]\",\"$subscriptionFields[2]\",\"$subscriptionFields[4]\",\"$subscriptionFields[5]\",\"$subscriptionFields[6]\",\"$subscriptionFields[8]\",\"$subscriptionFields[13]\",\"$subscriptionFields[14]\",\"$subscriptionFields[15]\",\"$subscriptionFields[16]\",\"$subscriptionFields[17]\",\"$subscriptionFields[18]\",\"$subscriptionFields[25]\",\"$subscriptionFields[26]\",\"$subscriptionFields[27]\"\n";
} else {
log_error("Line could not be parsed: $eachSubscriptionLine\n");
exit 1;
}
}
close(NEWSUBSCRIPTIONDATA);
open( my $subscriberData, '<:encoding(utf8)', $subscriberFile ) || die "Could not open '$subscriberFile' $!\n";
if ( "$isSubscriberHeaderPresesnt" eq "true" ) {
$subscriberHeader = <$subscriberData>;
}
while ( my $eachSubscriberLine = <$subscriberData> ) {
chomp $eachSubscriberLine;
if ( $csv->parse($eachSubscriberLine) ) {
#subscriberFields = $csv->fields();
$status = system("grep \"^[\\\"]*${subscriberFields[0]}[\\\"]*\\\$\" $subscriptionimsifile >>/dev/null");
if ( $status != 0 ) {
log_only(
"Adding back subscriber details, because unable to get IMSI details from subscription file : \"#subscriberFields\""
);
print NEWSUBSCRIBERDATA "\"$subscriberFields[0]\",\"$subscriberFields[1]\",\"$subscriberFields[2]\",\"$subscriberFields[6]\",,\"$subscriberFields[7]\",,,\n";
}
} else {
log_error("Line could not be parsed: $eachSubscriberLine\n");
exit 1;
}
}
close(NEWSUBSCRIBERDATA);
`sed -i -e '1 s|SUBSCRIPTION_ID|SUBSCRIPTION_IDREF|g' -e '1 s|SUBS_CATEGORY|SUBSCRIPTION_PLAN|g' -e '1 s|SUBS_STATE|SUBS_TYPE|g' -e '1 s|CUST_CATEGORY|CUSTOMER_SEGMENTATION|g' $newSubscriberFile`
or checkExit( $?, "Unable to update header info in subscriber fi le" );
General advice:
Don't use backticks to parse your input. Perl is perfectly capable of doing this with a while loop and split.
Misspelling variable names is going to screw you. Don't. isSubscriptionHeaderPresesnt
mixing your open calls - 3 argument with lexicals is generally preferred, but mismatching isn't nice.
Using the text string "false" in lieu of a boolean is horrible. Don't do it. Someone someday is going to do the equivalent of print "true" if "false" and it's going to break.
The most 'expensive' operation your script will be doing is reading the files. That's almost always true. So find something other than syscalls to grep or sed require full-rereading of the files you're targeting. Assuming subscriptionFile and subscriberFile are your biggies, you're reading them multiple times - you're running a cut that reads the whole thing. A dos2unix that reads the whole thing. A grep that reads the whole thing. And then you're opening it, and reading the whole thing.
your last line is a sed which will... re-read your output file, entirely, and apply a line by line transform to it.

Perl Help Needed: Replacing values

I am having an input file like this:
Input file
I need to replace the value #pSBSB_ID="*" of #rectype=#pRECTYPE="SBSB" with #pMEME_SSN="034184233", value of #pRECTYPE="SMSR", ..and have to delete the row where #rectype='#pRECTYPE="SMSR", '
Example:
So, after changes have been made, the file should be like this:
....#pRECTYPE="SBSB", #pGWID="17199269", #pINPUT_METHOD="E", #pGS08="005010X220A1", #pSBSB_FAM_UPDATE_CD="UP", #pSBSB_ID="034184233".....
....#pRECTYPE="SBEL", #pSBEL_EFF_DT="01/01/2013", #pSBEL_UPDATE_CD="TM", #pCSPD_CAT="M", #pCSPI_ID="MHMO1003"
.
.
.
Update
I tried below mentioned code:
Input file extension: mms and there are multiple files to process.
my $save_for_later;
my $record;
my #KwdFiles;
my $r;
my $FilePath = $ARGV[0];
chdir($FilePath);
#KwdFiles = <*>;
foreach $File(#KwdFiles)
{
unless(substr($File,length($File)-4,length($File)) eq '.mms')
{
next;
}
unless(open(INFILE, "$File"))
{
print "Unable to open file: $File";
exit(0);
}
print "Successfully opened the file: \"$File\" for processing\n\n";
while ( my $record = <INFILE> ) {
my %r = $record =~ /\#(\w+) = '(.*?)'/xg;
if ($r{rectype} eq "SMSR") {
$save_for_later = $r{pMEME_SSN};
next;
}
elsif ($r{rectype} eq "SBSB" and $r{pSBSB_ID} eq "*") {
$record =~ s|(\#pSBSB_ID = )'.*?'|$1'$save_for_later'|x;
}
close(INFILE);
}
}
But, I am still not getting the updated values in the file.
#!/usr/bin/perl
open IN, "< in.txt";
open OUT, "> out.txt";
my $CUR_RECID = 1^1;
while (<IN>) {
if ($CUR_RECID) {
s/recname='.+?'/recname='$CUR_RECID'/ if /rectype='DEF'/;
$CUR_RECID = 1^1;
print OUT;
}
$CUR_RECID = $1 if /rectype='ABC'.+?rec_id='(.+?)'/;
}
close OUT;
close IN;
Try that whole code. No need a separate function; This code does everything.
Run this script from your terminal with the files to be modified as arguments:
use strict;
use warnings;
$^I = '.bak'; #modify original file and create a backup of the old ones with .bak appended to the name
my $replacement;
while (<>) {
$replacement = $1 if m/(?<=\#pMEME_SSN=)("\d+")/; #assume replacement will be on the first line of every file.
next if m/^\s*\#pRECTYPE="SMSR"/;
s/(?<=\#pSBSB_ID=)("\*")/$replacement/g;
print;
}

Perl script.file handling issues

I have written a Perl script:
#!/usr/bin/perl
use strict;
use warnings;
my $file_name;
my $ext = ".text";
my $subnetwork2;
my %files_list = ();
opendir my $dir, "." or die "Cannot open directory: $!";
my #files = readdir $dir;
sub create_files() {
my $subnetwork;
open(MYFILE, 'file.txt');
while (<MYFILE>) {
if (/.subnetwork/) {
my #string = split /[:,\s]+/, $_;
$subnetwork = $string[2];
}
if (/.set/ && (defined $subnetwork)) {
my #string = split /[:,\s]+/, $_;
my $file = $subnetwork . $string[1];
open FILE, ">", "$file.text" or die $!;
close(FILE);
}
}
close(MYFILE);
}
sub create_hash() {
foreach (#files) {
if (/.text/) {
open($files_list{$_}, ">>$_") || die("This file will not open!");
}
}
}
sub init() {
open(MYFILE3, 'file.txt');
while (<MYFILE3>) {
if (/.subnetwork/) {
my #string3 = split /[:,\s]+/, $_;
$subnetwork2 = $string3[2];
last;
}
}
close(MYFILE3);
}
sub main_process() {
init;
create_files;
create_hash;
open(MYFILE1, 'file.txt');
while (<MYFILE1>) {
if (/.subnetwork/) {
my #string3 = split /[:,\s]+/, $_;
$subnetwork2 = $string3[2];
}
if (/.set/) {
my #string2 = split /[:,\s]+/, $_;
$file_name = $subnetwork2 . $string2[1] . $ext;
}
if (/.domain/ || /.end/ || ($. < 6)) {
my $domain = $_;
foreach (#files) {
if (/.text/ && /$subnetwork2/) {
prnt { $files_list{$_} } "$domain";
}
}
}
elsif ($. >= 6) {
print { $files_list{$file_name} } "$_";
}
}
close(MYFILE1);
foreach my $val (values %files_list) { close($val); }
closedir $dir;
}
main_process;
This script creates files in the current directory based upon the content of file.txt, and then open those files again.
Then it starts processing file.txt and redirects the lines according to the filename set dynamically.
This setting of the file name is also based upon the data in the file file.txt.
The problem that I am facing here is that the redirection is only to a single file. That means there is some problem with the file handle.
All the files that are expected to be created are created perfectly but the data goes into only one of them.
I doubt if there is a problem with the file handle that I am using while redirecting.
Could anyone please help?
Sample input file is below:
..cnai #Generated on Thu Aug 02 18:33:18 2012 by CNAI R21D06_EC01, user tcssrpi
..capabilities BASIC
.utctime 2012-08-02 13:03:18
.subnetwork ONRM_ROOT_MO:NETSim_BAG
.domain BSC
.set BAG01
AFRVAMOS="OFF"
AWBVAMOS="OFF"
ALPHA=0
AMRCSFR3MODE=1,3,4,7
AMRCSFR3THR=12,21,21
AMRCSFR3HYST=2,3,3
AMRCSFR3ICM=
AMRCSFR4ICM=
USERDATA=""
.set BAG02
AFRVAMOS="OFF"
AWBVAMOS="OFF"
ALPHA=0
AMRCSFR3MODE=1,3,4,7
AMRCSFR3THR=12,21,21
AMRCSFR3HYST=2,3,3
..end
The problem that i am facing is during execution:
> process.pl
Use of uninitialized value in ref-to-glob cast at process.pl line 79, <MYFILE1> line 6.
Can't use string ("") as a symbol ref while "strict refs" in use at process.pl line 79, <MYFILE1> line 6.
The problem i can understand is with this line:
print { $files_list{$_} } "$domain";
but i am unable to understand why!!
The output i need is :
> cat NETSim_BAGBAG01.text
.set BAG01
AFRVAMOS="OFF"
AWBVAMOS="OFF"
ALPHA=0
AMRCSFR3MODE=1,3,4,7
AMRCSFR3THR=12,21,21
AMRCSFR3HYST=2,3,3
AMRCSFR3ICM=
AMRCSFR4ICM=
USERDATA=""
> cat NETSim_BAGBAG02.text
.set BAG02
AFRVAMOS="OFF"
AWBVAMOS="OFF"
ALPHA=0
AMRCSFR3MODE=1,3,4,7
AMRCSFR3THR=12,21,21
AMRCSFR3HYST=2,3,3
>
Your problem in following lines:
open(PLOT,">>$_") || die("This file will not open!");
$files_list{$_}=*PLOT;
You should replace they with:
open($files_list{$_},">>$_") || die("This file will not open!");
This portion of your code is the key:
open(PLOT,">>$_") || die("This file will not open!");
$files_list{$_}=*PLOT;
The problem is that you are essentially using the filehandle PLOT as a global variable; every single entry in your hash is pointing to this same filehandle. Replace with something like this:
local *PLOT;
open(PLOT,">>$_") || die("This file will not open!");
$files_list{$_}=*PLOT;
You have got youself very entangled with this program. There is no need for the hash table or the multiple subroutines.
Here is a quick refactoring of your code that works with your data and writes files NETSim_BAG.BAG01.text and NETSim_BAG.BAG02.text. I put a dot between the subnet and the set to make the names a little clearer.
use strict;
use warnings;
my $out_fh;
open my $fh, '<', 'file.txt' or die $!;
my ($subnetwork, $set, $file);
while (<$fh>) {
if ( /^\.subnetwork\s+\w+:(\w+)/ ) {
$subnetwork = $1;
}
elsif ( /^\.set\s+(\w+)/ and $subnetwork) {
$set = $1;
$file = "$subnetwork.$set.text";
open $out_fh, '>', $file or die qq(Unable to open "$file" for output: $!);
print $out_fh;
}
elsif ( /^\.\.end/ ) {
undef $subnetwork;
undef $file;
}
if (/^[^.]/ and $file) {
print $out_fh $_;
}
}