#bash #escaping #fish #dash #zsh #byte-string

shell-quote

A Rust library for shell-quoting strings, e.g. for interpolating into a Bash script.

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 编码

Download history 1688/week @ 2024-05-02 789/week @ 2024-05-09 825/week @ 2024-05-16 1142/week @ 2024-05-23 2840/week @ 2024-05-30 1542/week @ 2024-06-06 2082/week @ 2024-06-13 1582/week @ 2024-06-20 1958/week @ 2024-06-27 789/week @ 2024-07-04 1905/week @ 2024-07-11 1680/week @ 2024-07-18 783/week @ 2024-07-25 605/week @ 2024-08-01 642/week @ 2024-08-08 1039/week @ 2024-08-15

每月3,510次下载
用于 5 crates

Apache-2.0

6MB
818

shell-quote

shell-quote 通过一种方式转义字符串,使得它们可以被插入到shell脚本中,而不会存在它们被解释为多个参数(如Bash的word splitting)、路径(Bash的pathname expansion)、shell元字符、函数调用或其他语法的风险。这通常不仅仅是用引号包裹一个字符串那么简单。

此包实现了对GNU BashZ Shellfish 以及包括 Dash 在内的类似 /bin/sh 的shell的转义。

它可以接受许多不同类型的字符串和字节字符串作为输入

并输出为以下类型(或推入)

灵感来源于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可能具有类似或不同的行为;请查阅它们的文档。

当我们使用&strString作为输入类型时,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作为最低公共分母会带来其他问题;仔细阅读其文档以了解限制。

功能标志

以下都是默认启用的

要限制对特定shell的支持,您必须在 Cargo.toml 中禁用此crate的默认功能,并重新启用您想要的功能。例如

[dependencies]
shell-quote = { version = "*", default-features = false, features = ["bash"] }

依赖关系