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

When i tried to extract name and number and print in a file then they are being repeated. I tried with and if condition to prevent the repeating with an regex at the start but not successful.

Like Naresh -> 8890328840
Naresh -> 8890328840
Naresh -> 8890328840
Naresh -> 8890328840
Naresh -> 8890328840

file.vsf structure is:

BEGIN:VCARD
VERSION:3.0
N:;Naresh;;;
FN:Naresh
TEL;TYPE=CELL;TYPE=PREF:+917734807608
END:VCARD

Code i tried is:

use strict; use warnings; my $filename = $ARGV[0]; my ($name, $number); open my $fh, "<", "$filename" or die "$!"; open my $fh2, ">", "list.txt" or die "$!"; while(my $line = <$fh>) { if( /!^\s*FN/ || /!^\s*TEL/ ) { next ; } elsif( $line =~ /^\s*FN:(\w+\s*\w*)\b/ ) { $name = $1; } elsif( $line =~ /^\s*TEL;TYPE=CELL;TYPE=PREF:([+|(?:91)]?\d{10})\b +/ ) { $number = $1; } printf $fh2 "%15s -> %d\n", $name, $number ; } close $fh2 or die "$!"; close $fh or die "$!";

I appreciate your time taken to read and answer. Thank u in advance.:)

Replies are listed 'Best First'.
Re: How to extract Name and No from .vcf file.
by GrandFather (Saint) on Aug 03, 2015 at 05:36 UTC

    Nice of you to use strictures, but pretty dumb to ignore the warnings they generate! Your "additional" test is doomed because it doesn't test the input line and the regular expressions are broken. The remaining code is doomed because you need to process each record as a unit, which is not what the code does. Instead consider:

    use strict; use warnings; local $/ = 'END:VCARD'; while (my $record = <DATA>) { my ($name, $number) = $record =~ /FN:([^\n;]+).*\nTEL;[^\n]*PREF:([^\n;]+)/s; next if !defined $number; printf "%15s -> %s\n", $name, $number; } __DATA__ BEGIN:VCARD VERSION:3.0 N:;Naresh;;; FN:Naresh TEL;TYPE=CELL;TYPE=PREF:+917734807608 END:VCARD

    Prints:

    Naresh -> +917734807608

    This code is not robust, but may help as a starting point for you.

    Premature optimization is the root of all job security
Re: How to extract Name and No from .vcf file.
by kevbot (Vicar) on Aug 03, 2015 at 05:45 UTC
    Hello shankonit,

    I see that pme already showed you working code for parsing the file yourself. Alternatively, you could use the vCard module to access the data in your vcf files. For example,

    file.vcf, Note: the vCard module requires windows line endings in the vcf file
    BEGIN:VCARD VERSION:3.0 N:;Naresh;;; FN:Naresh TEL;TYPE=CELL;TYPE=PREF:+917734807608 END:VCARD
    test.pl
    #!/usr/bin/env perl use strict; use warnings; use vCard; my $vcard = vCard->new; $vcard->load_file('file.vcf'); print "Full Name: ", $vcard->full_name, "\n"; my $pref_phone_num; foreach my $phone ( @{$vcard->phones} ){ if($phone->{preferred} == 1){ $pref_phone_num = $phone->{number}; } } print "Preferred Phone Number: ", $pref_phone_num, "\n"; exit;
    Output of test.pl
    Name: Naresh Preferred Phone Number: +917734807608
Re: How to extract Name and No from .vcf file.
by pme (Monsignor) on Aug 03, 2015 at 05:25 UTC
    Hi shankonit,

    I hope the comments help you to understand the code.

    #!/usr/bin/perl use strict; use warnings; my $filename = $ARGV[0]; my ($name, $number); open my $fh, "<", "$filename" or die "$!"; open my $fh2, ">", "list.txt" or die "$!"; while (<$fh>) { # read line to variable $_ chomp; # removes any trailing str +ing from $_ if ( /^FN:(.*)/ ) { # get the name $name = $1; } elsif ( /=PREF:(.*)/ ) { # get the number $number = $1; printf $fh2 "%15s -> %s\n", $name, $number; # %d changed to %s in + order to keep leading '+' } } close $fh2 or die "$!"; close $fh or die "$!";
Re: How to extract Name and No from .vcf file.
by shankonit (Acolyte) on Aug 03, 2015 at 05:46 UTC

    Hey i made it yeap..:)

    use strict; use warnings; my $filename = $ARGV[0]; my ($name, $number); open my $fh, "<", "$filename" or die "$!"; open my $fh2, ">", "list.txt" or die "$!"; while(my $line = <$fh>) { if( $line =~ /^\s*FN:(\w+\s*\w*)\b/ ) { $name = $1; } elsif( $line =~ /^\s*TEL;TYPE=CELL;TYPE=PREF:([+|(?:91)]?\d{10})\b +/ ) { $number = $1; if( defined($name) && defined($number) ) { printf $fh2 "%15s -> %d\n", $name, $number ; } } } close $fh2 or die "$!"; close $fh or die "$!";
      How about command line parameter checking?
      ... my $filename = $ARGV[0]; my ($name, $number); die "Usage: $0 filename\n" unless $filename; # checking command line p +arameter ...
Re: How to extract Name and No from .vcf file.
by vinoth.ree (Monsignor) on Aug 03, 2015 at 05:49 UTC

    use strict; use warnings; my $filename = $ARGV[0]; my ($name, $number); open my $fh, "<", "$filename" or die "$!"; open my $fh2, ">", "list.txt" or die "$!"; my @matches=(); while(my $line = <$fh>) { if (grep { $line =~ $_ } qr/^\s*FN/, qr/\s*TEL/){ if( $line =~ /^\s*FN:(.*)/ ) { push(@matches,$1); } elsif( $line =~ /^\s*TEL;TYPE=CELL;TYPE=PREF:(.*)/ ) { push(@matches , $1); } } else{ next; } } print $fh2 "@matches" ; close $fh2 or die "$!"; close $fh or die "$!";

    All is well. I learn by answering your questions...