Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

adding ";" to void elements

by steph_bow (Pilgrim)
on Feb 12, 2008 at 14:50 UTC ( #667578=perlquestion: print w/replies, xml ) Need Help??

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

Hello, Could you check this ?

I have a file (excel csv file )with the following structure

a;3 b;2;3 c;5;4 d;6

Is there a way to add ";" at the end of the lines which have only two elements ? Thanks

Replies are listed 'Best First'.
Re: adding ";" to void elements
by Limbic~Region (Chancellor) on Feb 12, 2008 at 14:57 UTC
    steph_bow,
    The naive way to do this might look like:
    #!/usr/bin/perl use strict; use warnings; while (<DATA>) { chomp; my @col = split /;/; push @col, '' for @col .. 2; print join ';', @col; print "\n"; } __DATA__ a;3 b;2;3 c;5;4 d;6
    A less naive solution would use a module from CPAN such as Text::CSV or Text::xSV. To understand why that is a better approach, take a few minutes with Super Search.

    Update: As noted by tye in the CB, this solution was originally not tested. I added chomp and changed @col .. 3; to @col .. 2;

    Cheers - L~R

      You get a similar solution using a very useful idiom if you replace

      my @col = split /;/; push @col, '' for @col .. 2; print join ';', @col;
      with
      my $len = 3; print join ';', (split(/;/), ('') x $len)[0 .. $len-1];
      assuming that there are at most two semi-colons in the string. The focus here is the way to create the default trailing elements. This is quite useful when you create hashes, where it's imperative to not have any missing (or extra) elements. For instance:
      my %foo = map { (split /:/, $_, 2)[0, 1] } # Implicit "default" undef. qw/ foo:bar baz zip:zap:zoom / ; use Data::Dumper; print Dumper(\%foo); __END__ $VAR1 = { 'baz' => undef, 'foo' => 'bar', 'zip' => 'zap:zoom' };
      A naive
      my %foo = map { split /:/ } ...;
      would've been disastrous.

      lodin

Re: adding ";" to void elements
by johngg (Canon) on Feb 12, 2008 at 15:24 UTC
    This works for two, one or even zero elements.

    use strict; use warnings; print map { qq{@{ [ join q{;}, @{ $_ } == 3 ? ( @{ $_ } ) : ( @{ $_ }, ( q{} ) x ( 3 - @{ $_ } ) ) ] }\n} } map { chomp; [ split m{;} ] } <DATA>; __END__ a;3 b;2;3 c;5;4 d;6 f

    The output.

    a;3; b;2;3 c;5;4 d;6; ;; f;;

    I hope this is useful.

    Cheers,

    JohnGG

Re: adding ";" to void elements
by poolpi (Hermit) on Feb 12, 2008 at 15:11 UTC
    #!/usr/bin/perl use strict; use warnings; map { print if s/\A (\w;\d) (?!;\d) / $1; /xms } <DATA>; __DATA__ a;3 b;2;3 c;5;4 d;6
    Output : a;3; d;6;
    hth,

    Poolpi
      map { print ... }

      That's worth at least two fifteen-yard penalties right there! I'm sort of horrified and impressed.

        It's for error checking, of course
        any { !$_ } map { print ... } ... and die;
        ;)
Re: adding ";" to void elements
by jwkrahn (Monsignor) on Feb 12, 2008 at 16:34 UTC
    $ echo "a;3 b;2;3 c;5;4 d;6" | perl -pe'y/;//==1&&s/$/;/' a;3; b;2;3 c;5;4 d;6;
      I went beyond the spec, and padded lines with no semi-colons too...
      perl -e 's^$^";"x(2-y-;--)^e' -p data
      ---
      my name's not Keith, and I'm not reasonable.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (2)
As of 2022-10-07 18:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred way to holiday/vacation is:











    Results (30 votes). Check out past polls.

    Notices?