Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xsv table displays values with escaped "s incorrectly #337

Open
Kinrany opened this issue Feb 6, 2024 · 7 comments
Open

xsv table displays values with escaped "s incorrectly #337

Kinrany opened this issue Feb 6, 2024 · 7 comments

Comments

@Kinrany
Copy link

Kinrany commented Feb 6, 2024

Example file:

header
a
"a"
""""

Expected output:

header
a
a
"

Real output:

header
a
a
""""
@BurntSushi
Copy link
Owner

xsv table doesn't print the parsed contents of CSV data. It just rewrites the input CSV as tab-delimited CSV, and then expands the tabs in the output as per elastic tabstops. This is easy to see in the implementation:

xsv/src/cmd/table.rs

Lines 49 to 71 in 4278b85

pub fn run(argv: &[&str]) -> CliResult<()> {
let args: Args = util::get_args(USAGE, argv)?;
let rconfig = Config::new(&args.arg_input)
.delimiter(args.flag_delimiter)
.no_headers(true);
let wconfig = Config::new(&args.flag_output)
.delimiter(Some(Delimiter(b'\t')));
let tw = TabWriter::new(wconfig.io_writer()?)
.minwidth(args.flag_width)
.padding(args.flag_pad);
let mut wtr = wconfig.from_writer(tw);
let mut rdr = rconfig.reader()?;
let mut record = csv::ByteRecord::new();
while rdr.read_byte_record(&mut record)? {
wtr.write_record(record.iter().map(|f| {
util::condense(Cow::Borrowed(f), args.flag_condense)
}))?;
}
wtr.flush()?;
Ok(())
}

It does seem plausible that it would be better to print the parsed contents (i.e., after unescaping quotes).

@Kinrany
Copy link
Author

Kinrany commented Mar 26, 2024

The thing that confused me the most was that it does remove the quotes around "a".

Is the output of xsv table intended to be parseable as CSV too?

@BurntSushi
Copy link
Owner

The thing that confused me the most was that it does remove the quotes around "a".

Yes, because the CSV writer knows when quotes are necessary. They aren't necessary to write a.

Is the output of xsv table intended to be parseable as CSV too?

No. As I said, the tabs are expanded to spaces. So it's very deliberately not CSV. It's for human consumption. Which is arguably why this should be treated as a bug and the quotes should be unescaped.

@Kinrany
Copy link
Author

Kinrany commented Mar 26, 2024

That's what I thought!

Can I help? Xsv is a great tool 😄

@vmchale
Copy link

vmchale commented Mar 29, 2024

xsv table doesn't print the parsed contents of CSV data. It just rewrites the input CSV as tab-delimited CSV, and then expands the tabs in the output as per elastic tabstops. This is easy to see in the implementation:

xsv/src/cmd/table.rs

Lines 49 to 71 in 4278b85

pub fn run(argv: &[&str]) -> CliResult<()> {
let args: Args = util::get_args(USAGE, argv)?;
let rconfig = Config::new(&args.arg_input)
.delimiter(args.flag_delimiter)
.no_headers(true);
let wconfig = Config::new(&args.flag_output)
.delimiter(Some(Delimiter(b'\t')));
let tw = TabWriter::new(wconfig.io_writer()?)
.minwidth(args.flag_width)
.padding(args.flag_pad);
let mut wtr = wconfig.from_writer(tw);
let mut rdr = rconfig.reader()?;
let mut record = csv::ByteRecord::new();
while rdr.read_byte_record(&mut record)? {
wtr.write_record(record.iter().map(|f| {
util::condense(Cow::Borrowed(f), args.flag_condense)
}))?;
}
wtr.flush()?;
Ok(())
}

It does seem plausible that it would be better to print the parsed contents (i.e., after unescaping quotes).

I ran into something similar for xsv fmt --ascii. Printing the parsed contents would be much more useful of a feature; one turns to ASV precisely so that you don't need to escape strings!

@Kinrany
Copy link
Author

Kinrany commented Mar 29, 2024

xsv fmt --table? 🤔

@BurntSushi
Copy link
Owner

xsv table doesn't print the parsed contents of CSV data. It just rewrites the input CSV as tab-delimited CSV, and then expands the tabs in the output as per elastic tabstops. This is easy to see in the implementation:

xsv/src/cmd/table.rs

Lines 49 to 71 in 4278b85

pub fn run(argv: &[&str]) -> CliResult<()> {
let args: Args = util::get_args(USAGE, argv)?;
let rconfig = Config::new(&args.arg_input)
.delimiter(args.flag_delimiter)
.no_headers(true);
let wconfig = Config::new(&args.flag_output)
.delimiter(Some(Delimiter(b'\t')));
let tw = TabWriter::new(wconfig.io_writer()?)
.minwidth(args.flag_width)
.padding(args.flag_pad);
let mut wtr = wconfig.from_writer(tw);
let mut rdr = rconfig.reader()?;
let mut record = csv::ByteRecord::new();
while rdr.read_byte_record(&mut record)? {
wtr.write_record(record.iter().map(|f| {
util::condense(Cow::Borrowed(f), args.flag_condense)
}))?;
}
wtr.flush()?;
Ok(())
}

It does seem plausible that it would be better to print the parsed contents (i.e., after unescaping quotes).

I ran into something similar for xsv fmt --ascii. Printing the parsed contents would be much more useful of a feature; one turns to ASV precisely so that you don't need to escape strings!

xsv fmt --ascii should definitely not print the parsed contents. It should print CSV data. And insert quoting when necessary. But it does look like it is inserting quotes when it shouldn't for --ascii.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants