shellwords
Version:
Manipulate strings according to the word parsing rules of the UNIX Bourne shell.
95 lines (81 loc) • 2.05 kB
text/typescript
const scan = (
string: string,
pattern: RegExp,
callback: (match: RegExpMatchArray) => void,
) => {
let result = "";
while (string.length > 0) {
const match = string.match(pattern);
if (match && match.index != null && match[0] != null) {
result += string.slice(0, match.index);
result += callback(match);
string = string.slice(match.index + match[0].length);
} else {
result += string;
string = "";
}
}
return result;
};
/**
* Splits a string into an array of tokens in the same way the UNIX Bourne shell does.
*
* @param line A string to split.
* @returns An array of the split tokens.
*/
export const split = (line = "") => {
const words = [];
let field = "";
scan(
line,
/\s*(?:([^\s\\'"]+)|'((?:[^'\\]|\\.)*)'|"((?:[^"\\]|\\.)*)"|(\\.?)|(\S))(\s|$)?/,
(match) => {
const [_raw, word, sq, dq, escape, garbage, separator] = match;
if (garbage != null) {
throw new Error(`Unmatched quote: ${line}`);
}
if (word) {
field += word;
} else {
let addition;
if (sq) {
addition = sq;
} else if (dq) {
addition = dq;
} else if (escape) {
addition = escape;
}
if (addition) {
field += addition.replace(/\\(?=.)/, "");
}
}
if (separator != null) {
words.push(field);
field = "";
}
},
);
if (field) {
words.push(field);
}
return words;
};
/**
* Escapes a string so that it can be safely used in a Bourne shell command line.
*
* @param str A string to escape.
* @returns The escaped string.
*/
export const escape = (str = "") => {
return str
.replace(/([^A-Za-z0-9_\-.,:/@\n])/g, "\\$1")
.replace(/\n/g, "'\n'");
};
/**
* Builds a command line string from an argument list.
*
* @param array An array of string arguments.
* @returns The command line string.
*/
export const join = (array: string[]) =>
array.map((element) => escape(element)).join(" ");