我可以使用"std::p ath::P ath"的"strip_prefix"来替换动态前缀吗?



我之所以有兴趣这样做,是因为我的路径中有一部分将保持不变,但我希望将其与其所有父部分一起删除。

因此,如果我们说,

some/unknown/path/foo/bar/baz

我想回来

bar/baz

但期望我只知道foo/...直接推进我关心的那部分道路。

也许strip_prefix是错误的方法,所以如果有更好的方法,我当然希望被指向这个方向。

strip_prefix不会做你想做的事,因为它需要你知道要去除的前缀。但是,您可以使用iter通过路径组件获取迭代器,然后使用标准Iterator方法仅从所需的部件生成新PathBuf

下面是一个示例(尝试一下(:

let p = path::Path::new("some/unknown/path/foo/bar/baz");
let q: path::PathBuf = p.iter()   // iterate over path components
.skip_while(|s| *s != "foo")  // skip everything before "foo"
.skip(1)                      // skip "foo" itself
.collect();                   // collect the rest into a PathBuf
println!("{:?}", q); // prints "bar/baz"

(这将分配一个新的PathBuf。Shepmaster的回答显示了如何在不分配的情况下获得引用原件的&Path

然后,您可以使用to_strto_string_lossyinto_os_stringOsString::into_string来获得可以变成String的东西。

另请参阅:如何将 PathBuf 转换为字符串

虽然我认为 trentcl 的答案更干净,但值得展示一些非分配版本。

使用Path::strip_prefix

要使用Path::strip_prefix,您需要知道前缀。我们可以通过沿着原始路径的parent向上走,直到找到ends_with"foo"的路径来生成它。

use std::path::Path;
fn thing1<P>(path: &P) -> Result<&Path, ()>
where
P: AsRef<Path> + ?Sized,
{
let original = path.as_ref();
let mut prefix = original;
while !prefix.ends_with("foo") {
prefix = match prefix.parent() {
Some(p) => p,
None => return Err(()),
};
}
original.strip_prefix(prefix).map_err(|_| ())
}
fn main() {
let x = thing1("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}

使用迭代器

我们可以遍历路径的各个部分,在它不是"foo"时获取值。一旦我们足够推进迭代器,我们就可以将其余部分作为路径。

use std::path::Path;
fn thing2<P>(path: &P) -> &Path
where
P: AsRef<Path> + ?Sized,
{
let path = path.as_ref();
let mut i = path.iter();
for _ in i.by_ref().take_while(|c| *c != "foo") {}
i.as_path()
}
fn main() {
let x = thing2("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}

当"foo"不存在时,这将返回一个空路径。

相关内容

  • 没有找到相关文章

最新更新