То, что делают оболочки при разбиении строки командной строки на аргументы, далеко не тривиально, особенно когда вы хотите обрабатывать такие вещи, как цитирование.Например, ваш код должен передавать следующие утверждения:
assert_eq!(split(r#""foo\"bar""#), vec!["foo\"bar"]);
assert_eq!(split(r#""foo"#), vec!["\"foo"]); // Or error
Если вы не считаете, что простого разбиения на пробел достаточно для вашего варианта использования, вам действительно следует использовать ящик типа shell-words
или shlex
.shlex
предоставляет преимущество в том, что он может возвращать итератор, что позволяет избежать ненужных распределений, но, с другой стороны, позволяет легко пропустить ошибку во втором тесте, приведенном выше:
extern crate shell_words;
extern crate shlex;
use shell_words::split;
use shlex::Shlex;
fn main() {
assert_eq!(split(r#"a b"#).unwrap(), vec!["a", "b"]);
let mut lex = Shlex::new(r#"a b"#);
assert_eq!(lex.by_ref().collect::<Vec<_>>(), vec!["a", "b"]);
assert!(!lex.had_error); // ← Don't forget this check!
assert_eq!(split(r#"a "b c""#).unwrap(), vec!["a", "b c"]);
let mut lex = Shlex::new(r#"a "b c""#);
assert_eq!(lex.by_ref().collect::<Vec<_>>(), vec!["a", "b c"]);
assert!(!lex.had_error); // ← Don't forget this check!
assert_eq!(split(r#""foo\"bar""#).unwrap(), vec!["foo\"bar"]);
let mut lex = Shlex::new(r#""foo\"bar""#);
assert_eq!(lex.by_ref().collect::<Vec<_>>(), vec!["foo\"bar"]);
assert!(!lex.had_error); // ← Don't forget this check!
assert!(split(r#""foo"#).is_err());
// assert_eq!(Shlex::new(r#""foo"#).collect::<Vec<_>>(), vec!["\"foo"]);
let mut lex = Shlex::new(r#""foo"#);
lex.by_ref().for_each (drop);
assert!(lex.had_error); // ← Don't forget this check!
}