如何在Rust命令参数中使用引号

3

我疯了。我想在Rust中生成这个命令git log --grep="foo"。这个命令在命令行中可以正常工作。

所以我尝试像这样执行它。

Command::new("git")
         .arg("log")
         .arg("--grep=\"foo\"")
         .spawn() 

那个不行。

如果我改成这样,就可以让它工作:

Command::new("git")
         .arg("log")
         .arg("--grep=foo")
         .spawn()

但是这只适用于可以省略引号的简单情况,所以它会运行git log --grep=foo,这并不是我想要的。我尝试了许多不同版本的format!等方法,但都没有成功。我都快抓狂了。
我尝试使用dtruss来追踪它,找出Rust实际使用的内容,但我也没有成功。 :/
更新
好的,我解决了这个问题。这有点棘手(至少对我来说是这样)。
我要运行的命令是git log --grep="foo|bar" -E。这需要在命令行中加上引号。但是重要的是要注意它需要与-E参数结合使用。
但是在Rust中,我需要删除引号。
Command::new("git")
    .arg("log")
    .arg("-E")
    .arg("--grep=foo|bar")
    .spawn()

我仍然想知道为什么在 Rust 中我必须省略引号。


1
有什么需要引号的例子吗?(即,没有内部引号就无法正常工作的内容。)我相信引号都是由 shell 处理的,传递给可执行文件的参数没有任何引号(而 Rust 是以同样的方式直接传递它们)。 - huon
1
换句话说,Rust 中的嵌入引号就像在 shell 中编写 --grep='"foo"' 一样,即查找字符串 "foo" 的文字本身,包括引号。 - huon
在shell中输入echo --grep="foo"会确认引号是由shell解释的。但是在rust中调用该命令时并不需要这些引号。 - wingedsubmariner
顺便问一下,“That doesn't work.” 是什么意思?你是否遇到了编译错误? - Levans
我更新了答案,以展示完整的情况。 - Christoph
2个回答

4
我仍然想知道为什么在Rust中我必须省略引号。
因为没有shell解释它们。
当您从shell启动命令时,您需要它们,因为git log --grep=foo|bar -E将被解释为将git log --grep=foo管道输出到bar -E
然而,在shell解释命令后,git接收到的参数实际上是log--grep=foo|bar-E
在从Rust调用命令时,没有shell解释命令,所以您不需要引号。加上引号就相当于从shell运行此命令。
git log --grep='"foo|bar"' -E

1
哇,我真的缺乏基本的UNIX知识。感谢您提供详细的答案! - Christoph

2

虽然Levans的回答很好,但还有其他潜在的选择。

我喜欢shell_words crate,它可以将包含完整命令行的String解析为参数向量,这些参数可以传递给Command。

从技术上讲,您可以编写以下代码:

let cmd=r#"git log --grep="foo""#;
let args = shell_words::split(cmd).unwrap();

这启发我将其打包成一个小的cli_runner库,我认为这对于测试和获取CLI应用程序的报告很有用。

使用它,我们可以编写如下代码:

let cmd=r#"git log --grep="foo""#;
let output = cli_runner::run(cmd);
assert!(output.status.success());
let so: String = cli_runner::get_stdout(&output);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接