【问题标题】:Can I use `std::path::Path`'s `strip_prefix` to replace a dynamic prefix?我可以使用 `std::path::Path` 的 `strip_prefix` 来替换动态前缀吗?
【发布时间】:2018-10-11 01:31:21
【问题描述】:

我对此感兴趣的原因是因为我的路径的一部分将保持不变,但我希望将其连同其所有父部分一起删除。

如果我们说,

some/unknown/path/foo/bar/baz

我想回来

bar/baz

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

也许strip_prefix 是错误的方法,所以如果有更好的方法可以做到这一点,我当然希望能指出这个方向。

【问题讨论】:

  • 您想像strip_prefix 那样返回Path,还是可以构建一个新的PathBuf 并返回它?
  • 最终我需要一个String--所以如果这能让我们到达那里,可以返回PathBuf

标签: path rust


【解决方案1】:

strip_prefix 不会做你想做的事,因为它要求你知道要剥离的前缀。但是,您可以使用iter 获取路径组件的迭代器,然后使用标准的Iterator 方法仅从您想要的部分构建一个新的PathBuf

这是一个示例 (try it):

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"

(这将分配一个新的PathBufShepmaster's answer 展示了如何在不分配的情况下获得一个引用原始的&Path。)

然后您可以使用to_strto_string_lossyinto_os_string 加上OsString::into_string 来获得可以变成String 的东西。

另见:How to convert the PathBuf to String

【讨论】:

    【解决方案2】:

    虽然我认为trentcl's answer is cleaner,但值得展示一些非分配版本。

    使用Path::strip_prefix

    要使用Path::strip_prefix,您需要知道前缀。我们可以通过沿着原始路径的parents 向上走,直到找到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);
    }
    

    使用迭代器

    我们可以iterate 覆盖路径,taking values while 这不是“foo”。一旦我们足够先进的迭代器,我们就可以得到剩余的as a path

    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”不存在时,这将返回一个空路径。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 2022-08-20
      相关资源
      最近更新 更多