Rust通过Command调用bash时如何转义参数内嵌套双引号
问题原因
编译失败的核心原因是两层语法规则的转义没有处理对:
- 第一层是Rust本身的字符串语法规则:普通双引号包裹的Rust字符串内部,直接出现双引号会被编译器判定为字符串结束,后续内容会被识别为非法语法,直接报编译错误。
- 第二层是参数传递规则:Rust的
Command::arg是直接把参数作为独立argv项传给子进程,不会经过当前shell解析,不需要额外为当前shell做转义,只需要保证传给bash -c的字符串和你原本要执行的bash命令完全一致即可,不需要修改原bash命令逻辑。
正确写法
优先用Rust的原始字符串字面量r#"..."#,这种写法下字符串内部的双引号、反斜杠、$符号都不需要额外转义,直接把原bash命令完整塞进去就行,完全满足不修改原bash命令的要求:
Command::new("/bin/bash") .arg("-c") // 原始字符串内直接放原bash命令即可,不需要改逻辑 .arg(r#"version=$(awk -F ' = ' '$1 ~ /version/ { gsub(/["]/, "", $2); printf("%s",$2) }' Cargo.toml)"#)
如果不用原始字符串,用普通双引号字符串的话,只需要把字符串内部所有的双引号前加反斜杠\转义即可,写法如下:
Command::new("/bin/bash") .arg("-c") .arg("version=$(awk -F ' = ' '$1 ~ /version/ { gsub(/[\"/], \"\", $2); printf(\"%s\",$2) }' Cargo.toml)")
注意事项
- 你之前代码里写的
$$1、$$2是多余的:这种写法是在当前交互式shell里敲命令时,为了防止当前shell提前展开$1/$2变量才需要的转义,用Command传参时不经过当前shell解析,直接写$1、$2即可,bash收到-c的参数后,会识别到awk脚本是单引号包裹的,不会展开内部的$变量,会原封不动传给awk执行,和你原命令的执行逻辑完全一致。 - 原始字符串的闭合标记
#数量可以调整,如果你的命令里出现了连续的"后面跟#的情况,只需要增加两边的#数量即可,比如用r##"..."##,绝大多数场景下单个#足够使用。
内容的提问来源于stack exchange,提问作者blueStack453
相关产品推荐
相关产品推荐

