10个版本 (6个重大更改)
0.7.1 | 2024年7月12日 |
---|---|
0.6.1 | 2024年6月27日 |
0.5.0 | 2023年11月27日 |
0.3.0 | 2022年4月3日 |
0.1.0 | 2020年2月5日 |
#147 in 编码
每月3,510次下载
用于 5 crates
6MB
818 行
shell-quote
shell-quote 通过一种方式转义字符串,使得它们可以被插入到shell脚本中,而不会存在它们被解释为多个参数(如Bash的word splitting)、路径(Bash的pathname expansion)、shell元字符、函数调用或其他语法的风险。这通常不仅仅是用引号包裹一个字符串那么简单。
此包实现了对GNU Bash、Z Shell、fish 以及包括 Dash 在内的类似 /bin/sh
的shell的转义。
它可以接受许多不同类型的字符串和字节字符串作为输入
&str
和String
&bstr::BStr
和bstr::BString
&[u8]
和Vec<u8>
&OsStr
和OsString
(在UNIX上)&Path
和PathBuf
并输出为以下类型(或推入)
灵感来源于Haskell的shell-escape包。
示例
当使用原始字节进行引号时,可以直接调用Sh
的、Dash
的、Bash
的、Fish
的、以及Zsh
的相关函数
use shell_quote::{Bash, Dash, Fish, Sh, Zsh};
// No quoting is necessary for simple strings.
assert_eq!(Sh::quote_vec("foobar"), b"foobar");
assert_eq!(Dash::quote_vec("foobar"), b"foobar"); // `Dash` is an alias for `Sh`
assert_eq!(Bash::quote_vec("foobar"), b"foobar");
assert_eq!(Zsh::quote_vec("foobar"), b"foobar"); // `Zsh` is an alias for `Bash`
assert_eq!(Fish::quote_vec("foobar"), b"foobar");
// In all shells, quoting is necessary for strings with spaces.
assert_eq!(Sh::quote_vec("foo bar"), b"foo' bar'");
assert_eq!(Dash::quote_vec("foo bar"), b"foo' bar'");
assert_eq!(Bash::quote_vec("foo bar"), b"$'foo bar'");
assert_eq!(Zsh::quote_vec("foo bar"), b"$'foo bar'");
assert_eq!(Fish::quote_vec("foo bar"), b"foo' bar'");
也可以使用扩展特性QuoteRefExt
,它提供了一个quoted
函数
use shell_quote::{Bash, Sh, Fish, QuoteRefExt};
let quoted: String = "foo bar".quoted(Bash);
assert_eq!(quoted, "$'foo bar'");
let quoted: Vec<u8> = "foo bar".quoted(Sh);
assert_eq!(quoted, b"foo' bar'");
let quoted: String = "foo bar".quoted(Fish);
assert_eq!(quoted, "foo' bar'");
或者使用扩展特性QuoteExt
将引号字符串推入缓冲区
use shell_quote::{Bash, QuoteExt};
let mut script: bstr::BString = "echo ".into();
script.push_quoted(Bash, "foo bar");
script.extend(b" > ");
script.push_quoted(Bash, "/path/(to)/[output]");
assert_eq!(script, "echo $'foo bar' > $'/path/(to)/[output]'");
关于字符串编码的说明
这里我们以Bash
为例,但其他shell可能具有类似或不同的行为;请查阅它们的文档。
当我们使用&str
或String
作为输入类型时,U+0080以上的UTF-8码点将直接写入引号形式,就像它们在UTF-8中的编码一样,即字节相同且没有转义序列。与此相比,使用不同的输入类型
# use shell_quote::{Bash, QuoteRefExt};
let data: &str = "café";
let data_utf8_quoted_from_string_type: Vec<u8> = data.quoted(Bash);
assert_eq!(&data_utf8_quoted_from_string_type, b"$'caf\xC3\xA9'"); // UTF-8, verbatim.
let data_utf8_quoted_from_bytes: Vec<u8> = data.as_bytes().quoted(Bash);
assert_eq!(&data_utf8_quoted_from_bytes, b"$'caf\\xC3\\xA9'"); // Now hex escaped!
因此,假设您需要使用非UTF-8的文本编码,则必须在传递给此crate中的函数之前将字符串类型进行编码。
例如,字符'é'(U+00E9)
- 在ISO-8859-1中,它由单个字节
0xE9
表示。 - 在UTF-8中,它由两个字节
0xC3 0xA9
表示。
使用假设的encode_iso_8859_1
函数
# use shell_quote::{Bash, QuoteRefExt};
# fn encode_iso_8859_1(_s: &str) -> &[u8] {
# &[99, 97, 102, 233]
# }
let data = "café";
let data_utf8_quoted: Vec<u8> = data.quoted(Bash);
assert_eq!(&data_utf8_quoted, b"$'caf\xC3\xA9'"); // UTF-8: 2 bytes for é.
let data_iso_8859_1: &[u8] = encode_iso_8859_1(data);
let data_iso_8859_1_quoted: Vec<u8> = data_iso_8859_1.quoted(Bash);
assert_eq!(&data_iso_8859_1_quoted, b"$'caf\\xE9'"); // ISO-8859-1: 1 byte, hex escaped.
兼容性
Sh
可以作为Bash、Z Shell以及类似/bin/sh
的shell(如Dash)的最低公共分母。然而,fish的引号规则差异很大,因此必须使用Fish
来编写fish脚本。
请注意,使用Sh
作为最低公共分母会带来其他问题;仔细阅读其文档以了解限制。
功能标志
以下都是默认启用的
bstr
:支持bstr::BStr
和bstr::BString
。bash
:支持 Bash 和 Z Shell。fish
:支持 fish。sh
:支持类似于/bin/sh
的shell,包括 Dash。
要限制对特定shell的支持,您必须在 Cargo.toml
中禁用此crate的默认功能,并重新启用您想要的功能。例如
[dependencies]
shell-quote = { version = "*", default-features = false, features = ["bash"] }