出于此问题的目的,CSV样式引用的字符串是一个字符串,其中:
"."Alo""ha"→ Alo"ha."A""" e"无法解析错误输入,例如.这是一个A",然后是垃圾e".我尝试了几件事,其中没有一件完全有效.
我得到的最接近,感谢Mozilla IRC上#nom用户粉红色的一些帮助:
use std::error as stderror; /* Avoids needing nightly to compile */
named!(csv_style_string<&str, String>, map_res!(
terminated!(tag!("\""), not!(peek!(char!('"')))),
csv_string_to_string
));
fn csv_string_to_string(s: &str) -> Result<String, Box<stderror::Error>> {
Ok(s.to_string().replace("\"\"", "\""))
}
Run Code Online (Sandbox Code Playgroud)
这不能正确捕获字符串的结尾.
我也试图使用re_match!宏r#""([^"]|"")*""#,但这总是导致Err::Incomplete(1).
这是一种方法:
use nom::types::CompleteStr;
use nom::*;
named!(csv_style_string<CompleteStr, String>,
delimited!(
char!('"'),
map!(
many0!(
alt!(
// Eat a " delimiter and the " that follows it
tag!("\"\"") => { |_| '"' }
| // Normal character
none_of!("\"")
)
),
// Make a string from a vector of chars
|v| v.iter().collect::<String>()
),
char!('"')
)
);
fn main() {
println!(r#""Alo\"ha" = {:?}"#, csv_style_string(CompleteStr(r#""Alo""ha""#)));
println!(r#""" = {:?}"#, csv_style_string(CompleteStr(r#""""#)));
println!(r#"bad format: {:?}"#, csv_style_string(CompleteStr(r#""A""" e""#)));
}
Run Code Online (Sandbox Code Playgroud)
(我用完整的名称编写了它,但是像您这样的解决方案基于外部函数而不是map!()每个字符,也可以工作,并且可能更有效。)
这里的神奇之处在于使用 CompleteStr,它也可以解决您的正则表达式问题。这基本上表明nom该输入之后不会有任何内容(否则,nom假设您正在执行流解析器,因此可能会出现更多输入)。
"这是必需的,因为我们需要知道如果 a 是输入到 的最后一个字符,该怎么办nom。根据它后面的字符(另一个",普通字符,或 EOF),我们必须做出不同的决定 - 因此结果Incomplete,意味着nom没有足够的输入来做出决定。告诉nomEOF 接下来出现可以解决这种犹豫不决的问题。
进一步阅读作者的博客:Incompletehttp ://unhandledexpression.com/general/2018/05/14/nom-4-0-faster-safer-simpler-parsers.html#dealing-with-incomplete-usagenom
您可能会注意到,这个解析器实际上并不拒绝无效输入,而是解析开头并返回其余部分。如果您将此解析器用作另一个解析器中的子解析器,则后者会将剩余部分提供给下一个子解析器,这也会崩溃(因为它需要逗号),从而导致整个解析器失败。
如果你不想这样,你可以进行csv_style_string匹配peek!(alt!(char!(',')|char!('\n")|eof!()))。
| 归档时间: |
|
| 查看次数: |
372 次 |
| 最近记录: |