我想通过 nom 库将YMD日期解析为四种形式(“ 20190919”,“ 2019.09.19”,“ 2019-09-19”和“ 2019/09/19”)
我从iso8601解析器开始,该解析器仅解析“ YYYY-MM-DD”格式。而且,我尝试匹配分隔符并将其重新用于下一个匹配,例如在正则表达式(\d{4})([.-/]?)(\d{2})\2(\d{2})中。
原来该代码有效:
fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
let (i, y) = year(i)?;
// Match separator if it exist.
let (i, sep) = opt(one_of(".-/"))(i)?;
let (i, m) = month(i)?;
// If first separator was matched then try to find next one.
let (i, _) = if let Some(sep) = sep {
tag(&[sep as u8])(i)?
} else {
// Support the same signature as previous branch.
(i, &[' ' as u8][..])
};
let (i, d) = day(i)?;
Ok((
i,
DateType::YMD {
year: y,
month: m,
day: d,
},
))
}
但是显然看起来很奇怪。
有一些标称工具可以更合适地做到这一点吗?
(关于 nom 功能以及如何正确执行操作的问题。不仅仅是这个特定示例。)
答案 0 :(得分:1)
您的解决方案足够不错。我只能提供一个真正的建议:
fn parse_ymd(i: &[u8]) -> IResult<&[u8], DateType> {
...
// If first separator was matched then try to find next one.
let i = match sep {
Some(sep) => tag(&[sep as u8])(i)?.0,
_ => i,
};
...
}
您可能不熟悉直接访问元组元素的语法。来自rust book:
除了通过模式匹配进行结构分解之外,我们还可以通过使用句点(。)和要访问的值的索引直接访问元组元素。
在这种情况下,它可以省去尝试匹配两个手臂的签名的笨拙。