Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

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
    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;
      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.


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.



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;

      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?

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2022-10-06 17:44 GMT
Find Nodes?
    Voting Booth?
    My preferred way to holiday/vacation is:

    Results (26 votes). Check out past polls.