Created
November 4, 2017 22:18
-
-
Save boxdot/8abd5eccec95dd74d0a35d33463ae53b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fs::File; | |
use std::io::BufRead; | |
use std::io::Write; | |
use std::path::PathBuf; | |
#[derive(Debug)] | |
struct Args { | |
input: PathBuf, | |
column: String, | |
replacement: String, | |
output: PathBuf, | |
} | |
#[inline] | |
fn parse_args() -> Result<Args, String> { | |
let mut args = std::env::args(); | |
args.next(); | |
Ok(Args { | |
input: PathBuf::from(args.next().ok_or(String::from("Missing input argument"))?), | |
column: args.next().ok_or(String::from("Missing column argument"))?, | |
replacement: args.next().ok_or(String::from("Missing column argument"))?, | |
output: PathBuf::from(args.next().ok_or(String::from("Missing input argument"))?), | |
}) | |
} | |
#[inline] | |
fn find_column(line: &str, column: &str) -> Option<usize> { | |
for (index, token) in line.split(",").enumerate() { | |
if token == column { | |
return Some(index); | |
} | |
} | |
None | |
} | |
#[inline] | |
fn output_err<T>(err: T) -> String | |
where | |
T: std::fmt::Debug, | |
{ | |
format!("Could not write to output file: {:?}", err) | |
} | |
fn do_work(args: Args) -> Result<(), String> { | |
// open file | |
let fin = File::open(args.input).map_err(|err| { | |
format!("Could not open input file: {}", err) | |
})?; | |
let mut input = std::io::BufReader::new(fin); | |
// find column in header | |
let mut line = String::new(); | |
input.read_line(&mut line).map_err(|err| { | |
format!("Could not read header: {}", err) | |
})?; | |
let column_index = find_column(&line, &args.column).ok_or(String::from( | |
"Could not find column", | |
))?; | |
// open output | |
let fout = File::create(args.output).map_err(|err| { | |
format!("Could not open input file: {}", err) | |
})?; | |
let mut output = std::io::BufWriter::new(fout); | |
output.write(line.as_bytes()).map_err(output_err)?; | |
// replace | |
for line in input.lines() { | |
for (index, token) in line.map_err(output_err)?.split(",").enumerate() { | |
if index > 0 { | |
output.write(b",").map_err(output_err)?; | |
} | |
if index == column_index { | |
output.write(args.replacement.as_bytes()).map_err( | |
output_err, | |
)?; | |
} else { | |
output.write(token.as_bytes()).map_err(output_err)?; | |
} | |
} | |
output.write(b"\n").map_err(output_err)?; | |
} | |
Ok(()) | |
} | |
fn main() { | |
let args = parse_args(); | |
let res = args.and_then(do_work); | |
::std::process::exit(match res { | |
Ok(_) => 0, | |
Err(err) => { | |
eprintln!( | |
"Error: {}\n\nUSAGE: csv <INPUT> <COLUMN> <REPLACEMENT> <OUTPUT>", | |
err | |
); | |
1 | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment