Rust 如何在a&;中找到子序列;[u8]切片?

Rust 如何在a&;中找到子序列;[u8]切片?,rust,Rust,我在二进制缓冲区上有一个&[u8]片。我需要解析它,但我想使用的许多方法(如str::find)似乎在切片上都不可用 我已经看到,我可以通过使用from\u utf8\u unchecked()将缓冲区片和模式转换为str,但这似乎有点危险(而且也非常危险) 如何在这个切片中找到子序列?实际上,我需要的是模式的索引,而不仅仅是部分的切片视图,因此我认为split不起作用。这里是一个基于迭代器的简单实现 fn find_subsequence(haystack: &[u8], needle

我在二进制缓冲区上有一个
&[u8]
片。我需要解析它,但我想使用的许多方法(如
str::find
)似乎在切片上都不可用

我已经看到,我可以通过使用
from\u utf8\u unchecked()
将缓冲区片和模式转换为
str
,但这似乎有点危险(而且也非常危险)


如何在这个切片中找到子序列?实际上,我需要的是模式的索引,而不仅仅是部分的切片视图,因此我认为
split
不起作用。

这里是一个基于迭代器的简单实现

fn find_subsequence(haystack: &[u8], needle: &[u8]) -> Option<usize> {
    haystack.windows(needle.len()).position(|window| window == needle)
}

fn main() {
    assert_eq!(find_subsequence(b"qwertyuiop", b"tyu"), Some(4));
    assert_eq!(find_subsequence(b"qwertyuiop", b"asd"), None);
}

我不认为标准库包含用于此的函数。一些libc有
memmem
,但目前libc板条箱没有包装此文件。但是,您可以使用
rust-bio
也实现了一些模式匹配算法。所有这些都应该比使用haystack.windows(..).position(..)更快

怎么样?看起来很强大。看这个

extern板条箱正则表达式;
使用regex::bytes::regex;
fn main(){
//看https://doc.rust-lang.org/regex/regex/bytes/
让re=Regex::new(r“say[^,]*”).unwrap();
让text=b“说foo,说bar,说baz”;
//从每个匹配中提取所有不带空终止符的字符串。
//此处展开是正常的,因为匹配需要“cstr”捕获才能匹配。
让CSTR:Vec=
关于国际贸易规则(文本)
.map(| c | c.get(0).unwrap().start())
.收集();
断言(CSTR,vec![0,9,18]);
}
我发现以下选项对此任务很有用:

use memmem::{Searcher, TwoWaySearcher};

let search = TwoWaySearcher::new("dog".as_bytes());
assert_eq!(
    search.search_in("The quick brown fox jumped over the lazy dog.".as_bytes()),
    Some(41)
);

人们感兴趣的是将
模式的概念扩展到任意切片:,。非常好。我想我基本上是用两个嵌套的for循环手工完成的。我正在寻找的子阵列都非常小,因此对我的问题来说,执行更复杂的操作(如KMP)是没有用的。虽然这是一个简短而好的解决方案,但请注意,该算法在O(| haystack |*| needle |)中运行。在大多数情况下,这并不重要,但对于更高级和(渐进)更快的算法,请参见。这最终会导致速度慢得令人无法接受。windows().position()比两个嵌套循环慢100倍。@JasonN 100x听起来很极端。你确定是用优化编译的吗?@JasonN你是如何处理两个嵌套循环的?这个解决方案应该编译成与一个循环相同的东西。
extern crate regex;

use regex::bytes::Regex;

fn main() {
    //see https://doc.rust-lang.org/regex/regex/bytes/

    let re = Regex::new(r"say [^,]*").unwrap();

    let text = b"say foo, say bar, say baz";

    // Extract all of the strings without the null terminator from each match.
    // The unwrap is OK here since a match requires the `cstr` capture to match.
    let cstrs: Vec<usize> =
        re.captures_iter(text)
          .map(|c| c.get(0).unwrap().start())
          .collect();

    assert_eq!(cstrs, vec![0, 9, 18]);
}
use memmem::{Searcher, TwoWaySearcher};

let search = TwoWaySearcher::new("dog".as_bytes());
assert_eq!(
    search.search_in("The quick brown fox jumped over the lazy dog.".as_bytes()),
    Some(41)
);