Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 234 additions & 0 deletions bin/csv-filter
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
#!/usr/bin/env ruby

require 'optparse'
require 'csv'

# Returns an array of names.
# \String +s+ contains a comma-separated list of names.
def parse_names(s)
s.split(",").collect(&:to_sym)
end

options = {}

parser = OptionParser.new

parser.version = CSV::VERSION
parser.banner = <<-BANNER
Usage: #{parser.program_name} [options]

Reads and parses the CSV text content of the standard input per the given input options.
From that content, generates CSV text per the given output options and writes
that text to the standard output.

Three options are similar for input and output:

- Row separator:

- The input row separator is determined:

- By option --input-row-sep, if given.
- Otherwise, by option --row-sep, if given.
- Otherwise, by auto-discovery.

- The output row separator is determined:

- By option --output-row-sep if given.
- Otherwise, by option --row-sep if given.
- Otherwise, as the newline character ("\\n").

- Column separator:

- The input column separator is determined:

- By option --input-col-sep, if given.
- Otherwise, by option --col-sep, if given.
- Otherwise, as the comma character (",").

- The output column separator is determined:

- By option --output-col-sep if given.
- Otherwise, by option --col-sep if given.
- Otherwise, as the comma character (",").

- Quote character:

- The input quote character is determined:

- By option --input-quote-char, if given.
- Otherwise, by option --quote-char, if given.
- Otherwise, as the double-quote character ('"').

- The output quote character is determined:

- By option --output-quote-char, if given.
- Otherwise, by option --quote-char, if given.
- Otherwise, as the double-quote character ('"').
BANNER

parser.separator(nil)
parser.separator(
'Input Options: see https://docs.ruby-lang.org/en/3.3/CSV.html#class-CSV-label-Options+for+Parsing'
)

parser.separator(nil)
parser.on('--converters=CONVERTERS',
'Input field converters;',
'CONVERTERS is comma-separated converter names (leading colon optional).'
) do |value|
options[:converters] = parse_names(value)
end
# parser.on('--empty_value STR',
# 'Value to be output for empty input field.') do |value|
# options[:empty_value] = value
# end
parser.on('--field-size-limit=N', Integer,
'Maximum field size (characters)') do |value|
options[:field_size_limit] = value
end
parser.on('--headers=ARG',
'Treat the first input row as headers;',
'ARG is true or comma-separated headers.'
) do |value|
options[:headers] = value == 'true' ? true : parse_names(value)
end
parser.on('--header-converters=CONVERTERS',
'Input header converters;',
'CONVERTERS is comma-separated converter names.'
) do |value|
options[:header_converters] = parse_names(value)
end
parser.on('--liberal-parsing',
'Attempt to parse non-conformant input.') do
options[:liberal_parsing] = :no_argument
end
# parser.on('--nil_value STR',
# 'Value to be substituted for nil input field.') do |value|
# options[:nil_value] = value
# end
# parser.on('--return_headers',
# 'Method shift returns header row.') do
# options[:return_headers] = :no_argument
# end
# parser.on('--skip_blanks',
# 'Ignore blank lines.') do
# options[:skip_blanks] = :no_argument
# end
# parser.on('--skip_lines STR',
# 'Ignore comment lines;',
# 'STR is converted to a Regexp that identifies comment lines.') do |value|
# options[:skip_lines] = Regexp.new(value)
# end
# parser.on('--strip',
# 'Strip whitespace from input fields.') do
# options[:strip] = :no_argument
# end
# parser.on('--unconverted_fields',
# 'Define method unconverted_fields for each created CSV::Row object.') do
# options[:unconverted_fields] = :no_argument
# end

parser.separator(nil)
parser.separator(
'Output Options: see https://docs.ruby-lang.org/en/3.3/CSV.html#class-CSV-label-Options+for+Generating'
)

parser.separator(nil)
# parser.on('--force_quotes',
# 'Double-quote each output field.') do
# options[:force_quotes] = :no_argument
# end
# parser.on('--quote_empty STR',
# 'Double-quote each empty output field;',
# 'STR is true or false.'
# ) do
# options[:quote_empty] = :no_argument
# end
# parser.on('--write_converters',
# 'Output field converters;',
# 'not implemented in CLI.'
# ) do |value|
# raise NotImplementedError.new('--write_converters is not implemented in the CLI.')
# end
# parser.on('--write_headers',
# 'Write headers to output.') do |value|
# options[:write_headers] = :no_argument
# end
# parser.on('--write_empty_value STR',
# 'Value to be substituted for empty output field.') do |value|
# options[:write_empty_value] = value
# end
# parser.on('--write_nil_value STR',
# 'Value to be substituted for nil output field.') do |value|
# options[:write_nil_value] = value
# end

parser.separator(nil)
parser.separator(
'Options only for CSV.filter: see https://docs.ruby-lang.org/en/3.3/CSV.html#method-c-filter'
)

parser.on('--input-col-sep=SEPARATOR',
'Input column separator string (aliased as --in-col-sep).') do |value|
options[:input_col_sep] = value
end
parser.on('--input-quote-char=CHAR',
'Input quote character (aliased as --in-quote-char.') do |value|
options[:input_quote_char] = value
end
parser.on('--input-row-sep=SEPARATOR',
'Input row separator string (aliased as --in-row-sep).'
) do |value|
options[:input_row_sep] = value
end
parser.on('--output-col-sep=SEPARATOR',
'Output column separator string (aliased as --out-col-sep).'
) do |value|
options[:output_col_sep] = value
end
parser.on('--output-quote-char=CHAR',
'Output quote character (aliased as --out-quote-char).') do |value|
options[:output_quote_char] = value
end
parser.on('--output-row-sep=SEPARATOR',
'Output row separator string (aliased as --out-row-sep).'
) do |value|
options[:output_row_sep] = value
end

parser.separator(nil)
parser.separator('Input/Output Options')

parser.separator(nil)
parser.on('-c', '--col-sep=SEPARATOR',
'Column separator string.') do |value|
options[:col_sep] = value
end
parser.on('-q', '--quote-char=CHAR',
'Quote character.') do |value|
options[:quote_char] = value
end
parser.on('-r', '--row-sep=SEPARATOR',
'Row separator string.'
) do |value|
options[:row_sep] = value
end

parser.separator(nil)
parser.separator('Generic Options')
parser.separator(nil)

parser.on('-h', '--help', 'Prints this help.') do
puts parser
exit
end

parser.on('-v', '--version', 'Prints version.') do
puts CSV::VERSION
exit
end

parser.parse!

CSV.filter(**options) do |row|
end
Loading
Loading