Могу ли я использовать `strip_prefix`` std :: path :: Path` для замены динамического префикса? - PullRequest
0 голосов
/ 01 мая 2018

Причина, по которой я заинтересован в этом, заключается в том, что есть часть моего пути, которая останется постоянной, но которую я хочу удалить вместе со всеми ее родительскими частями.

Так что, если мы скажем,

some/unknown/path/foo/bar/baz

Я хотел бы вернуть

bar/baz

Но с ожиданием, что я знаю только, foo/... напрямую проходит ту часть пути, которая мне небезразлична.

Возможно, strip_prefix - неправильный подход, поэтому, если есть лучший способ сделать это, я, безусловно, был бы признателен за указание в этом направлении.

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Хотя я думаю, что ответ trentcl чище , стоит показать несколько нераспределенных версий.

Использование Path::strip_prefix

Чтобы использовать Path::strip_prefix, вам необходимо знать префикс. Мы можем создать его, пройдя по parent s первоначального пути, пока не найдем тот, который 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" не существует.

0 голосов
/ 01 мая 2018

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. Ответ начальника магазина показывает, как получить &Path ссылку на оригинал без выделения.)

Затем вы можете использовать to_str, to_string_lossy или into_os_string плюс OsString::into_string, чтобы получить что-то это можно превратить в String.

См. Также: Как преобразовать PathBuf в строку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...