[wellylug] curly csv formatting

Grant McLean grant at mclean.net.nz
Fri Jul 9 13:24:13 NZST 2004


> the csv layout is now as follows:
>
> surname,firstname(s),date of birth, 1st qualification, various details
> ,       ,           ,             , 2nd qualification, various details
> ,       ,           ,             , 3rd qualification, various details
> ,       ,           ,             , 4th qualification, various details
> ..and so one until it gets to the next new client..

Are the empty fields really filled with spaces?  If not, here's a one-liner:

perl -n -F, -a -e '$F[$_] ||= $t[$_] foreach (0..2); print join(",", @F);
$t[$_] = $F[$_] foreach (0..2)' filename.csv

The -n means loop through each line in the named file.

The -F, -a means split each line on commas and store the fields in the
global array @F

Pulling apart the code in the -e ...

  $F[$_] ||= $t[$_] foreach (0..2)

This line introduces a temporary array @t (which will initially be empty)
and uses the ||= operator to copy the value from $t[n] to $F[n] for each of
the first three element if the current value in $F[n] is 'false' (ie: empty,
undefined or 0).

If you really do have spaces in the empty fields then spaces are not false
so you'd need to do something like this:

  foreach (0..2) { $F[$_] = $t[$_] unless $F[$_] =~ /\S/ }

Which only does the assignment if $F[n] does not contain a non-whitespace
character (sorry about the double negative)

  print join(",", @F);

This line reassembles the fields into a line and prints it out (the trailing
newline stayed attached to the last element in @F).

  $t[$_] = $F[$_] foreach (0..2)

This line unconditionally copies the first three elements from @F to @t.


It might look clearer as a script than a one-liner:

#!/usr/bin/perl  -w

use strict;

my(@F, @t);

while(<>) {
  @F = split /,/;
  foreach (0..2) { $F[$_] = $t[$_] unless $F[$_] =~ /\S/ }
  print join ",", @F;
  $t[$_] = $F[$_] foreach (0..2);
}


Cheers
Grant






More information about the wellylug mailing list