File Coverage

blib/lib/Fsdb/Filter/csv_to_db.pm
Criterion Covered Total %
statement 18 64 28.1
branch 0 12 0.0
condition n/a
subroutine 6 15 40.0
pod 5 5 100.0
total 29 96 30.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             #
4             # csv_to_db.pm
5             # Copyright (C) 2005-2007 by John Heidemann
6             # $Id: 6d26ba96e4a0b34fac3cb167418ed83bf90fe137 $
7             #
8             # This program is distributed under terms of the GNU general
9             # public license, version 2. See the file COPYING
10             # in $dblib for details.
11             #
12              
13             package Fsdb::Filter::csv_to_db;
14              
15             =head1 NAME
16              
17             csv_to_db - convert comma-separated-value data into fsdb
18              
19             =head1 SYNOPSIS
20              
21             csv_to_db
22              
23             =head1 DESCRIPTION
24              
25             Converts a comma-separated-value data stream to Fsdb format.
26              
27             The input is CSV-format (I fsdb).
28             The first row is taken to be the names of the columns.
29              
30             The output is two-space-separated fsdb.
31             (Someday more general field separators should be supported.)
32             Fsdb fields are normalized version of the CSV file:
33             spaces are converted to single underscores.
34              
35             =for comment
36             begin_standard_fsdb_options
37              
38             This module also supports the standard fsdb options:
39              
40             =over 4
41              
42             =item B<-d>
43              
44             Enable debugging output.
45              
46             =item B<-i> or B<--input> InputSource
47              
48             Read from InputSource, typically a file name, or C<-> for standard input,
49             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
50              
51             =item B<-o> or B<--output> OutputDestination
52              
53             Write to OutputDestination, typically a file name, or C<-> for standard output,
54             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
55              
56             =item B<--autorun> or B<--noautorun>
57              
58             By default, programs process automatically,
59             but Fsdb::Filter objects in Perl do not run until you invoke
60             the run() method.
61             The C<--(no)autorun> option controls that behavior within Perl.
62              
63             =item B<--help>
64              
65             Show help.
66              
67             =item B<--man>
68              
69             Show full manual.
70              
71             =back
72              
73             =for comment
74             end_standard_fsdb_options
75              
76              
77             =head1 SAMPLE USAGE
78              
79             =head2 Input:
80              
81             paper,papertitle,reviewer,reviewername,score1,score2,score3,score4,score5
82              
83             1,"test, paper",2,Smith,4,4,,,
84             2,other paper,3,Jones,3,3,,,
85              
86             =head2 Command:
87              
88             csv_to_db
89              
90             =head2 Output:
91              
92             #fsdb -F S paper papertitle reviewer reviewername score1 score2 score3 score4 score5
93             1 test, paper 2 Smith 4 4 - - -
94             2 other paper 3 Jones 3 3 - - -
95             # | csv_to_db
96              
97              
98             =head1 SEE ALSO
99              
100             L.
101             L.
102              
103              
104             =head1 CLASS FUNCTIONS
105              
106             =cut
107              
108             @ISA = qw(Fsdb::Filter);
109             $VERSION = 2.0;
110              
111 1     1   3468 use strict;
  1         1  
  1         24  
112 1     1   3 use Pod::Usage;
  1         1  
  1         65  
113 1     1   4 use Carp;
  1         2  
  1         37  
114              
115 1     1   4 use Text::CSV_XS;
  1         1  
  1         25  
116              
117 1     1   4 use Fsdb::Filter;
  1         2  
  1         13  
118 1     1   3 use Fsdb::IO::Writer;
  1         1  
  1         456  
119              
120              
121             =head2 new
122              
123             $filter = new Fsdb::Filter::csv_to_db(@arguments);
124              
125             Create a new csv_to_db object, taking command-line arguments.
126              
127             =cut
128              
129             sub new ($@) {
130 0     0 1   my $class = shift @_;
131 0           my $self = $class->SUPER::new(@_);
132 0           bless $self, $class;
133 0           $self->set_defaults;
134 0           $self->parse_options(@_);
135 0           $self->SUPER::post_new();
136 0           return $self;
137             }
138              
139              
140             =head2 set_defaults
141              
142             $filter->set_defaults();
143              
144             Internal: set up defaults.
145              
146             =cut
147              
148             sub set_defaults ($) {
149 0     0 1   my($self) = @_;
150 0           $self->SUPER::set_defaults();
151             }
152              
153             =head2 parse_options
154              
155             $filter->parse_options(@ARGV);
156              
157             Internal: parse command-line arguments.
158              
159             =cut
160              
161             sub parse_options ($@) {
162 0     0 1   my $self = shift @_;
163              
164 0           my(@argv) = @_;
165             $self->get_options(
166             \@argv,
167 0     0     'help|?' => sub { pod2usage(1); },
168 0     0     'man' => sub { pod2usage(-verbose => 2); },
169             'autorun!' => \$self->{_autorun},
170             'd|debug+' => \$self->{_debug},
171 0     0     'i|input=s' => sub { $self->parse_io_option('input', @_); },
172             'log!' => \$self->{_logprog},
173 0     0     'o|output=s' => sub { $self->parse_io_option('output', @_); },
174 0 0         ) or pod2usage(2);
175 0 0         pod2usage(2) if ($#argv >= 0);
176             }
177              
178             =head2 setup
179              
180             $filter->setup();
181              
182             Internal: setup, parse headers.
183              
184             =cut
185              
186             sub setup ($) {
187 0     0 1   my($self) = @_;
188              
189 0           $self->finish_fh_io_option('input');
190              
191 0           my $csv = $self->{_csv} = new Text::CSV_XS;
192              
193 0           my($header);
194 0           $header = $self->{_in}->getline;
195 0 0         my $e = $csv->parse($header) or croak $self->{_prog} . ": cannot parse header $header\n";
196 0           my(@columns) = Fsdb::IO::clean_potential_columns($csv->fields());
197              
198 0           $self->finish_io_option('output', -fscode => 'S', -cols => \@columns);
199             }
200              
201             =head2 run
202              
203             $filter->run();
204              
205             Internal: run over each rows.
206              
207             =cut
208             sub run ($) {
209 0     0 1   my($self) = @_;
210              
211 0           my $write_fastpath_sub = $self->{_out}->fastpath_sub();
212              
213 0           my $csv = $self->{_csv};
214 0           my $lineno = 0;
215 0           for (;;) {
216 0           my $line = $self->{_in}->getline;
217 0           $lineno++;
218 0 0         last if (!defined($line));
219 0           chomp $line;
220             # skip blank lines
221 0 0         next if ($line eq '');
222 0           my $e = $csv->parse($line);
223 0 0         if (! $e) {
224 0           carp "# csv conversion error in on line $lineno: " . $csv->error_diag() . "\n";
225 0           next; # skip error lines
226             };
227 0           my(@row) = $csv->fields();
228 0           grep { s/ +/ /g; } @row; # clean up for fsdb double-space separator
  0            
229 0           grep { s/^ *$/-/g; } @row; # add null values for fields
  0            
230 0           &{$write_fastpath_sub}(\@row);
  0            
231             };
232             }
233              
234              
235             =head1 AUTHOR and COPYRIGHT
236              
237             Copyright (C) 1991-2008 by John Heidemann
238              
239             This program is distributed under terms of the GNU general
240             public license, version 2. See the file COPYING
241             with the distribution for details.
242              
243             =cut
244              
245             1;