File Coverage

blib/lib/Fsdb/Filter/csv_to_db.pm
Criterion Covered Total %
statement 18 65 27.6
branch 0 12 0.0
condition n/a
subroutine 6 15 40.0
pod 5 5 100.0
total 29 97 29.9


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