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

Matching probem

by Nansh (Acolyte)
on May 29, 2017 at 05:52 UTC ( [id://1191475]=perlquestion: print w/replies, xml ) Need Help??

Nansh has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Hello, My file looks like below

Eg:

CARS TOYOTO Etios Innova Camry

+Fortuner Corolla

*.This is Class cars.

CARS HYUNDAI Verna i10 i20

+Eon Xcent

+Tucson

*.It is best cars.

CARS HONDA City Brio Amaze

+Accord

*.This is Luxury cars.

In my above file example under Toyoto what are all the cars are there that will come. same way in Honda and Hyundai as well.

First i need to match the car companies and put that in an array. Then for each of that car company we need to match the cars and put them in other array

For that my code is like below bt i am not able to get the correct output please help me to solve this
#!usr/bin/perl use Data::Dumper qw(Dumper); open(DATA,"/something/something/something") || die("Couldnt open the f +ile \n"); while(<DATA>) { if(/^\s*CARS\s*[A-Z]/) { ($car)=$_=/^\s*CARS\s*(\w+)/; push(@car_list,$car); } } foreach $one_car(@car_list) { open(DATA,"/something/something/something")|| die("Couldnt open the +file \n"); while(<DATA>) { if(/^\s*CARS\b$one_car\b/) { last if/\*\.(\w+)/; $/="*"; $data_next=<DATA>; print"$data_next\n"; $/="\n"; } } }

Replies are listed 'Best First'.
Re: Matching probem
by marinersk (Priest) on May 29, 2017 at 11:17 UTC

    Hello again, Nansh.

    I'm noticing a trend in your posts and would like to help you help us help you.

    It would be most helpful if you provided four things (you got two of them) in your questions:

    1. Sample code
    2. Sample input
    3. Expected output
    4. Actual output (including any error messages, warnings, diagnostics, etc.)

    And please, for the love of Perl, please

    use strict; use warnings;

    For example:


    Hi,

    Hello, My file looks like below:

    CARS TOYOTO Etios Innova Camry +Fortuner Corolla *.This is Class cars. CARS HYUNDAI Verna i10 i20 +Eon Xcent +Tucson *.It is best cars. CARS HONDA City Brio Amaze +Accord *.This is Luxury cars.

    In my above file example under Toyoto what are all the cars are there that will come. same way in Honda and Hyundai as well.

    I need to do the following:

    1. Match the car companies and put that in an array.
    2. For each of that car company, match the cars and put them in other array

    For that my code is like below:

    #!usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); open(DATA,"/something/something/something") || die("Couldnt open the + file \n"); while(<DATA>) { if(/^\s*CARS\s*[A-Z]/) { ($car)=$_=/^\s*CARS\s*(\w+)/; push(@car_list,$car); } } foreach $one_car(@car_list) { open(DATA,"/something/something/something")|| die("Couldnt open th +e file \n"); while(<DATA>) { if(/^\s*CARS\b$one_car\b/) { last if/\*\.(\w+)/; $/="*"; $data_next=<DATA>; print"$data_next\n"; $/="\n"; } } }

    I am expecting the output to look like this:

    (Here is where you show us what you were expecting)

    But instead, I'm getting this:

    (Here is where you show us what you actually got, including any error messages)

    If you start posting your questions this way, I think you'll find you get better quality answers. Also, by forcing yourself to think along these structured pathways, I think you'll find you learn Perl more quickly.

Re: Matching probem
by kcott (Archbishop) on May 29, 2017 at 09:13 UTC

    G'day Nansh,

    I'd consider using a hash. Use the makes for the main keys; you can always generate an array of them with keys if needed.

    You didn't explain what the lines starting with "*." were supposed to be. I've assumed some sort of comment and labelled them as such.

    You didn't explain why some models start with a "+": I've put them in separate arrays.

    #!/usr/bin/env perl use strict; use warnings; use Data::Dump; my %cars; my $models_re = qr{(?x: ^ ( \w+ ) \s+ ( [^*]+? ) \s+ [*][.] ( .*? ) \s +* $ )}; my $plus_re = qr{(?x: ^ [+] ( .* ) $ )}; { local $/ = 'CARS '; while (<DATA>) { chomp; next unless length; my ($make, $models, $comment) = /$models_re/; for (split /\s+/, $models) { if (/$plus_re/) { push @{$cars{$make}{models}{plus}}, $1; } else { push @{$cars{$make}{models}{plain}}, $_; } } $cars{$make}{comment} = $comment; } } dd \%cars; __DATA__ CARS TOYOTO Etios Innova Camry +Fortuner Corolla *.This is Class cars. CARS HYUNDAI Verna i10 i20 +Eon Xcent +Tucson *.It is best cars. CARS HONDA City Brio Amaze +Accord *.This is Luxury cars.

    Output:

    { HONDA => { comment => "This is Luxury cars.", models => { plain => ["City", "Brio", "Amaze"], plus = +> ["Accord"] }, }, HYUNDAI => { comment => "It is best cars.", models => { plain => ["Verna", "i10", "i20", "Xcent"], plus => ["Eon", "Tucson"], }, }, TOYOTO => { comment => "This is Class cars.", models => { plain => ["Etios", "Innova", "Camry", "Cor +olla"], plus => ["Fortuner"], }, }, }

    — Ken

Re: Matching probem
by NetWallah (Canon) on May 29, 2017 at 06:44 UTC
    This is what I could make of your requirements:
    #!usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); local $/="\nCARS"; while (<DATA>){ my @lines = split /\n/ ,$_; my ($manufacturer, $vendor) = $lines[0] =~m/^(?:CARS)?\s+(\w+)\s+( +\w.+)/; print "----- Got car $manufacturer (Sold by $vendor) ---\n"; my @cars = grep {/^\+/} @lines; print "\tCAR: $_\n" for @cars; } __DATA__ CARS TOYOTO Etios Innova Camry +Fortuner Corolla *.This is Class cars. CARS HYUNDAI Verna i10 i20 +Eon Xcent +Tucson *.It is best cars. CARS HONDA City Brio Amaze +Accord *.This is Luxury cars.
    OUTPUT:
    ----- Got car TOYOTO (Sold by Etios Innova Camry) --- CAR: +Fortuner Corolla ----- Got car HYUNDAI (Sold by Verna i10 i20) --- CAR: +Eon Xcent CAR: +Tucson ----- Got car HONDA (Sold by City Brio Amaze) --- CAR: +Accord

                    Once it hits the fan, the only rational choice is to sweep it up, package it, and sell it as fertilizer.

Re: Matching probem
by huck (Prior) on May 29, 2017 at 06:02 UTC

    I would never do it like you are trying, but i suspect one of the problems you face is that you never close the input file, so that once EOF is reached it stays eof forever

    Yoou will want a close DATA; before foreach $one_car(@car_list) and another before the last }

    Also DATA is not the best name to use for it has a magical meaning to perl as well

Re: Matching probem
by marinersk (Priest) on May 29, 2017 at 11:35 UTC

    Okay, so your first problem seems to be that you're not getting your input correctly. I've added strictand warnings and the commensurate mystatements, and then used Data::Dumperto show what you're collecting:

    #!usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); my @car_list = (); open(INPFIL,"cars.dat") || die("Couldnt open the file \n"); while(<INPFIL>) { if(/^\s*CARS\s*[A-Z]/) { my ($car)=$_=/^\s*CARS\s*(\w+)/; push(@car_list,$car); } } print Dumper @car_list; exit;

    The output shows you're collecting a bunch of 1s:

    S:\Steve\Dev\PerlMonks\P-2017-05-29@0722-Cars-Arrays-Groups>perl cars0 +.pl $VAR1 = 1; $VAR2 = 1; $VAR3 = 1;

    Nothing else matters until you fix that. This is a variant of what we used to, in the profession, call "garbage in, garbage out".

    Now, I could tell you why you're collecting 1s instead of car manufacturers, but it's a good exercise for you to take a stab at explaining why.

    What's your best guess(es)?

Re: Matching probem
by karlgoethebier (Abbot) on May 29, 2017 at 20:13 UTC

    TMTOWTDI with desperate effort to sanitize the weird data. And aren't Eon and Xcent different models?

    #!/usr/bin/env perl use strict; use warnings; use Data::Dump; undef $/; my $data = <DATA>; $data =~ s/\n+/ /g; my @cars = map { s/ $//; $_ } map { s/^ //; $_ } grep { $_ ne "" } split /CARS/, $data; my %cars; for (@cars) { my @record = map { s/ $//; $_ } split /\+|\*\./; my @basic = split / /, shift @record; my $brand = shift @basic; $cars{$brand}{models}{basic} = [@basic]; $cars{$brand}{comment} = pop @record; $cars{$brand}{models}{plus} = [ map { split( ' ', $_ ) } @record +]; } dd \%cars; __DATA__ CARS TOYOTO Etios Innova Camry +Fortuner Corolla *.This is Class cars. CARS HYUNDAI Verna i10 i20 +Eon Xcent +Tucson *.It is best cars. CARS HONDA City Brio Amaze +Accord *.This is Luxury cars.

    This yields:

    krls-mac-mini:Desktop karl$ ./cars.pl { HONDA => { comment => "This is Luxury cars.", models => { basic => ["City", "Brio", "Amaze"], plus = +> ["Accord"] }, }, HYUNDAI => { comment => "It is best cars.", models => { basic => ["Verna", "i10", "i20"], plus => ["Eon", "Xcent", "Tucson"], }, }, TOYOTO => { comment => "This is Class cars.", models => { basic => ["Etios", "Innova", "Camry"], plus => ["Fortuner", "Corolla"], }, }, }

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    Furthermore I consider that Donald Trump must be impeached as soon as possible

Re: Matching probem
by thanos1983 (Parson) on May 29, 2017 at 18:54 UTC

    Hello Nansh,

    Another not best way I would say, but I wanted to give it a try. :D

    #!usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); my %hash; my %cars; while(<>) { chomp; next if /^\s*#/; # skip comments next unless length; # skip white lines if ($_ =~ /^CARS/) { my @car_list = split ' ', $_; shift @car_list; # or splice @car_list, 0, 1; $cars{shift @car_list} = \@car_list; } elsif ($_ !~ /^CARS/) { my @keys = keys %cars; my @values = values %cars; $hash{$_}{$keys[0]} = shift @values; delete $cars{shift @keys}; } } continue { close ARGV if eof; # Not eof()! } print Dumper \%hash; __DATA__ CARS TOYOTO Etios Innova Camry Fortuner Corolla *.This is Class cars. CARS HYUNDAI Verna i10 i20 Eon Xcent Tucson *.It is best cars. CARS HONDA City Brio Amaze Accord *.This is Luxury cars. __OUTPUT__ $ perl test.pl input.txt $VAR1 = { '*.This is Luxury cars.' => { 'HONDA' => [ 'City', 'Brio', 'Amaze', 'Accord' ] }, '*.This is Class cars.' => { 'TOYOTO' => [ 'Etios', 'Innova', 'Camry', 'Fortuner', 'Corolla' ] }, '*.It is best cars.' => { 'HYUNDAI' => [ 'Verna', 'i10', 'i20', 'Eon', 'Xcent', 'Tucson' ] } };

    Update: Removing two unnecessary lines (code untested)

    Update2: Correcting buggy code.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-26 04:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found