libutil: add bashEscape, which escapes non-printing characters with $''

(cherry picked from commit ee91eec5cf)

Change-Id: I7e5c88ebe27c0a283982f8ac25f0fb0c6a6a6964
This commit is contained in:
Qyriad
2025-11-18 20:38:01 +01:00
parent d76581dbcb
commit ced467fe49
2 changed files with 40 additions and 2 deletions
+35 -2
View File
@@ -129,8 +129,41 @@ std::string shellEscape(const std::string_view s)
std::string r;
r.reserve(s.size() + 2);
r += "'";
for (auto & i : s)
if (i == '\'') r += "'\\''"; else r += i;
for (auto & i : s) {
if (i == '\'') {
// End the single quote, add a single backslash-escaped single quote,
// then start a single quote again.
// i.e., `I didn't know` becomes `'I didn'\''t know'`.
r += "'\\''";
} else {
r += i;
}
}
r += '\'';
return r;
}
std::string bashEscape(const std::string_view s)
{
std::string r;
r.reserve(s.size() + 2);
r += "'";
for (auto & i : s) {
if (!std::isprint(i)) {
// Close the single quote, start an "ANSI-C Quote" ($'foo'), add `\xXX`,
// close the ANSI-C Quote, and finally start a normal single quote again.
r += fmt("'$'\\x%02x''", static_cast<unsigned int>(static_cast<unsigned char>(i)));
} else if (i == '\'') {
// End the single quote, add a single backslash-escaped single quote,
// then start a single quote again.
// i.e., `I didn't know` becomes `'I didn'\''t know'`.
r += "'\\''";
} else {
r += i;
}
}
r += '\'';
return r;
}
+5
View File
@@ -191,6 +191,11 @@ std::string toLower(const std::string & s);
*/
std::string shellEscape(const std::string_view s);
/**
* Same as shellEscape, but also escapes nonprinting characters using $'ANSI C quotes'.
*/
std::string bashEscape(const std::string_view s);
/**
* Base64 encoding/decoding.
*/