It works well except for double quotes. I get " in the file as below
ip-prefix-list "UCS_SERVERS"
I am not using any external library for formatting. The device connection is made via the ssh2 crate. How can I just convert those back to a double quote?
writeln! doesn't escape characters. I'm not aware of anything in the standard library that does that. Either file is from a third party crate that escapes quotes, or new_line already contains them.
I don't understand. Raw strings work fine with writeln!, and don't change how interpolation works at all. You're going to need to provide more context.
I had to test this (playground) because I thought the raw string syntax would prevent the format string but apparently it does not! TIL.
In which case there's no need to use a raw string r#"..."# at all because there are no quotes in the source code.
It has no runtime effect at all.
Since printing and writing to the file appear to output differently, it's time to look more closely at file, or rather the impl of Write it is referring to. That must be escaping " and replacing them with ".
To clarify, the ”escaping” we are talking about is double quotes being replaced by " in your output. This is a form of escaping used by HTML and XML formats. (Do your dependencies include any HTML- or XML-writing libraries? Could the server be providing HTML or XML output?)
Can you provide more context from your code, or (even better) a simplified example we can use to reproduce the problem?
Does file in the above code have type std::fs::File, or some other type?
Have you tried writing a literal double quote to the file as a test?
writeln!(&mut file, "\"").unwrap();
How are you viewing the file and/or the standard output? Are you running this on your local laptop/desktop machine, or over a network connection of some sort?
Yes, this is over a network. I create a file and write the contents to it. This is all NETCONF, so it does comeback in XML. However vendors do have options for the portion of the response to come back as emulating a cli output. I don't have this problem with all vendors. I will respond with more context/details later. I want to sanitize the code first.
" escaping is valid XML, though optional outside of attributes (so "don't have this problem with all vendors" makes sense). If you are receiving XML, whether an entire document or a fragment of it, and you want to extract plain text from it, it is important that you do so through the means of an XML parser rather than anything else. It's tempting to do something like simply searching for an XML tag to extract the data, but that is not correct and will not be reliable. There are too many different-but-equivalent ways to write XML syntax. You must pass XML to an XML parser.
Ok, getting all the extraneous digits, hash signs, and new line characters allowed for a good XML parse and formatting using xml-rs. Still kind of bizarre though. These were agains NOKIA 7250's
Below is the code that reads from the SSH channel. What I do know is that the reply from NETCONF HELO message is perfect, the reply for get-config is not. You may notice that this code comes directly from an example on ssh2 crate docs.
fn read(channel: &mut Channel) -> Result<String, Box<dyn Error>> {
let mut result = String::new();
loop {
// If you plan to use this, be aware that reading 1 byte at a time is terribly
// inefficient and should be optimized for your usecase. This is just an example.
let mut buffer = [1u8; 3];
let bytes_read = channel.read(&mut buffer[..])?;
let s = String::from_utf8_lossy(&buffer[..bytes_read]);
result.push_str(&s);
if result.ends_with("]]>]]>") {
println!("Found netconf 1.0 terminator, breaking read loop");
break;
}
if result.ends_with("##") {
println!("Found netconf 1.1 terminator, breaking read loop");
break;
}
if bytes_read == 0 || channel.eof() {
println!("Buffer is empty, SSH channel read terminated");
break;
}
}
Ok(result)
This is the code reading from the ssh channel. It's straight from the example in ssh2 docs.
fn read(channel: &mut Channel) -> Result<String, Box<dyn Error>> {
let mut result = String::new();
loop {
// If you plan to use this, be aware that reading 1 byte at a time is terribly
// inefficient and should be optimized for your usecase. This is just an example.
let mut buffer = [1u8; 3];
let bytes_read = channel.read(&mut buffer[..])?;
let s = String::from_utf8_lossy(&buffer[..bytes_read]);
result.push_str(&s);
if result.ends_with("]]>]]>") {
println!("Found netconf 1.0 terminator, breaking read loop");
break;
}
if result.ends_with("##") {
println!("Found netconf 1.1 terminator, breaking read loop");
break;
}
if bytes_read == 0 || channel.eof() {
println!("Buffer is empty, SSH channel read terminated");
break;
}
}
Ok(result)
That looks like a weird kind of chunked transfer encoding, where #number means the next line contains number bytes of data. Once you strip that encoding, it should be valid XML.
HI all. I managed to get everything nicely formatted. I removed the NETCONF formatting with the Regex Crate. I then used xml-rs to get a nicely formatted file. However, is there anything that could write this to a string as opposed to stdout or a file? If not, is it acceptable to fork from git hub and try to implement this?