Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re^2: Parse file and creating hashes

by PerlMonger79 (Sexton)
on Jan 08, 2022 at 16:45 UTC ( [id://11140271]=note: print w/replies, xml ) Need Help??


in reply to Re: Parse file and creating hashes
in thread Parse file and creating hashes

Hello and thank you very much for your time dedicated to my plea for help. I would like a script that would use the following data and output the following.
702005010683593,5016683593,7020000024140 702005010640383,5016640383,7020000024150 310005010532143,5016532143,7020000034001 702005010637702,5016637702,7020000034001 702005010608274,5016608274,7020000034013 702005010608274,5016608274,7020000034013 310005010609604,5016609604,7020000034013 702005010510869,5016510869,7020000034013 702005010551513,5016551513,7020000034130 702005010551513,5016551513,7020000034130 702005010679719,5016679719,7020000034222 702005010527052,5016527052,7020000034222 702005010645458,5016645458,7020000034222
Logical processing of he info ...
$VAR1 = { '7020000024140' => [ '5016683593' ], '7020000024150' => [ '5016640383' ], '7020000034001' => [ '5016532143','5016637702' ], '7020000034013' => [ '5016608274','5016608274','5016609604','5016510869' ], '7020000034130' => [ '5016551513',5016551513' ], '7020000034222' => [ '5016679719','5016527052','5016645458' ] };
As I mentioned earlier the data is thousands of lines above is the logical processing of the info as I would treat it. In the end ONLY the array with numbers repeating more than 30 times would be printed as an output. For this sample purpose, I'm using arrays with numbers repeating more than once.
$VAR1 = { '7020000034013' => [ '5016608274' ], '7020000034130' => [ '5016551513' ] };
I apologize if I'm am not clear, I'm really trying to be as clear as I can with my explanation since I really need the help.

Replies are listed 'Best First'.
Re^3: Parse file and creating hashes
by tybalt89 (Monsignor) on Jan 08, 2022 at 17:55 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11140267 use warnings; my %answer; while( <DATA> ) { my (undef, $two, $three) = split /,|\n/; $answer{$three}{$two}++; } my $thirty = 1; # FIXME 1 for testing, should be 30 for my $href ( values %answer) { delete @{$href}{ grep $href->{$_} <= $thirty, keys %$href } } delete @answer{ grep 0 == %{ $answer{$_} }, keys %answer }; $_ = [ keys %$_ ] for values %answer; use Data::Dump 'dd'; dd \%answer; __DATA__ 702005010683593,5016683593,7020000024140 702005010640383,5016640383,7020000024150 310005010532143,5016532143,7020000034001 702005010637702,5016637702,7020000034001 702005010608274,5016608274,7020000034013 702005010608274,5016608274,7020000034013 310005010609604,5016609604,7020000034013 702005010510869,5016510869,7020000034013 702005010551513,5016551513,7020000034130 702005010551513,5016551513,7020000034130 702005010679719,5016679719,7020000034222 702005010527052,5016527052,7020000034222 702005010645458,5016645458,7020000034222

    Outputs:

    { "7020000034013" => [5016608274], "7020000034130" => [5016551513] }
Re^3: Parse file and creating hashes
by tybalt89 (Monsignor) on Jan 08, 2022 at 21:07 UTC

    Here's another way...

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11140267 use warnings; my $file = <<END; 702005010683593,5016683593,7020000024140 702005010640383,5016640383,7020000024150 310005010532143,5016532143,7020000034001 702005010637702,5016637702,7020000034001 702005010608274,5016608274,7020000034013 702005010608274,5016608274,7020000034013 310005010609604,5016609604,7020000034013 702005010510869,5016510869,7020000034013 702005010551513,5016551513,7020000034130 702005010551513,5016551513,7020000034130 702005010679719,5016679719,7020000034222 702005010527052,5016527052,7020000034222 702005010645458,5016645458,7020000034222 END open my $fh, '<', \$file or die; # FIXME change for your file my $thirty = 1; # FIXME 1 for testing, should be 30 my (%answer, %lines); $lines{ /,(.+)/ ? $1 : die "bad data <$_>" }++ while <$fh>; for ( keys %lines ) { my ($value, $key) = split ','; $lines{$_} > $thirty and push @{ $answer{$key} }, $value; } use Data::Dump 'dd'; dd \%answer;
      Hello, Thanks again for your help, I really appreciate it. I hate to bother ask, but is there a way to output without the use of Data::Dump? The issue is that the server where the script is hosted is on a private lan network which does not have access to the internet, I need to vpn in to work on it remotely, so I cannot install the module on the server. That's why I had the module use Excel::Writer::XLSX; because I was going to output to excel file as a report. I couldn't test the script. :(
      Thank you very much. I really appreciate all your help. With this part of the script done, I can continue with the other parts. Thanks again and God bless. :)
      The data in the text file is the same as before. Nothing different. The error i get is.

      bad data </home/vlr/archive/temp.txt> at ./vlr-cdma-test.pl line 32, <$fh> line 1.

      These are my codes. #vlr-cdma-parse.pl
      #!/usr/bin/perl -w use strict; use warnings; use Text::ParseWords; my $dir = "/home/vlr/archive/"; my $date = "20211201"; chomp($date); # Check directory for relevant files opendir(DIR, $dir) or die "Could not open ".$dir."\n"; my @dir = grep(/^USRINF.*.$date.*.1700.txt$/, readdir DIR); closedir DIR; my $file = $dir."temp.txt"; open my $FH, '>', $file; foreach $_(sort @dir){ my $DFile = $dir.$_; print "Processing: ".$DFile."\n"; # Open Data File and parse each line open my $DF, '<', $DFile or die "Can't open $DFile $!"; foreach $_ (<$DF>){ chomp( $_ ); if((length $_ > 0)&&($_ =~ /^\d{15}/)){ $_ =~ s/\s+/;/g; my($imsi,$mdn,$sec) = (quotewords('[\t;]+|,\s', 0, $_))[0, +1,3]; if((($imsi =~ /^\d{15}/)&&($imsi =~ /^(702|310)/))&&(($mdn + =~ /^\d{10}/)&&($mdn =~ /^(501)/))){ print $FH $imsi.",".$mdn.",".$sec."\n"; } } } close $DF; } close $FH;
      Then I would like to call the text file with your code. #vlr-cdma-test.pl
      #!/usr/bin/perl -w use strict; # https://perlmonks.org/?node_id=11140267 use warnings; use Data::Dumper qw(Dumper); my $dir = "/home/vlr/archive/"; my $file = $dir."temp.txt"; open my $fh, '<', \$file or die; # FIXME change for your file my $thirty = 1; # FIXME 1 for testing, should be 30 my (%answer, %lines); $lines{ /,(.+)/ ? $1 : die "bad data <$_>" }++ while <$fh>; for ( keys %lines ) { my ($value, $key) = split ','; $lines{$_} > $thirty and push @{ $answer{$key} }, $value; } open my $FH, '>', 'output.txt'; print $FH Dumper(\%answer); close $FH;

        Yep, Remove the backslash before $file in the open statement.

      Hi again. When I run your script it works fine, but when I try to call a text file from the directory where the data is previously stored I get the "bad data" error. Is there something I changed which is causing this error? How can I use the data from a called text file?
      #!/usr/bin/perl -w use strict; # https://perlmonks.org/?node_id=11140267 use warnings; use Data::Dumper qw(Dumper); my $dir = "/home/vlr/archive/"; my $file = $dir."temp.txt"; open my $fh, '<', \$file or die; # FIXME change for your file my $thirty = 1; # FIXME 1 for testing, should be 30 my (%answer, %lines); $lines{ /,(.+)/ ? $1 : die "bad data <$_>" }++ while <$fh>; for ( keys %lines ) { my ($value, $key) = split ','; $lines{$_} > $thirty and push @{ $answer{$key} }, $value; } open my $FH, '>', 'output.txt'; print $FH Dumper(\%answer); close $FH;
        open my $fh, '<', $file or die; # FIXME change for your file

        Remove the backslash, it is only used when you are treating a string as a file.

        Are the lines in the data file in a different format than the lines you showed as an example?

        Also, please show the complete line with the "bad data" error message, it will also show the line it thinks is bad.

      Hi, I don't think it is reading the text file. This was the output.

      $VAR1 = {};

      Thanks for taking the time to help.

        That would happen if there were no duplicates in your file.

Re^3: Parse file and creating hashes
by PerlMonger79 (Sexton) on Jan 08, 2022 at 16:53 UTC
    This is the script I have so far.
    #!/usr/bin/perl -w use strict; use warnings; use Text::ParseWords; use POSIX qw/strftime/; use Excel::Writer::XLSX; my $dir = "/home/vlr/archive/"; my $date = "20211201"; # Check directory for relevant files opendir(DIR, $dir) or die "Could not open ".$dir."\n"; my @dir = grep(/^USRINF.*.$date.*.1700.txt$/, readdir DIR); closedir DIR; my %btssec; foreach $_(sort @dir){ my $DFile = $dir.$_; print "Processing: ".$DFile."\n"; # Open Data File and parse each line open my $DF, '<', $DFile or die "Can't open $DFile $!"; foreach $_ (<$DF>){ chomp( $_ ); if((length $_ > 0)&&($_ =~ /^\d{15}/)){ $_ =~ s/\s+/;/g; my($imsi,$mdn,$sec) = (quotewords('[\t;]+|,\s', 0, $_))[0, +1,3]; if((($imsi =~ /^\d{15}/)&&($imsi =~ /^(702|310)/))&&(($mdn + =~ /^\d{10}/)&&($mdn =~ /^(501)/))){ #print $imsi.",".$mdn.",".$sec."\n"; =pod # The part below is the part of the script I need help with to p +rocess the parsed data whose output I'm posted as the snippet to proc +ess. if(!exists($btssec{$sec})){ print "New key:" . $sec ."\n"; $btssec{$sec} = $mdn; }elsif(exists($btssec{$sec})){ #push( @{$btssec{$sec}}, $mdn ); } =cut } } } close $DF; print "$_\n" for keys %btssec; }
    For now, the script I have in POD sucks it's not doing what I thought it would do. (sigh).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11140271]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (2)
As of 2024-04-26 00:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found