UNPKG

1.83 kBPlain TextView Raw
1const scan = (
2 string: string,
3 pattern: RegExp,
4 callback: (match: RegExpMatchArray) => void
5) => {
6 let result = "";
7
8 while (string.length > 0) {
9 const match = string.match(pattern);
10
11 if (match && match.index != null && match[0] != null) {
12 result += string.slice(0, match.index);
13 result += callback(match);
14 string = string.slice(match.index + match[0].length);
15 } else {
16 result += string;
17 string = "";
18 }
19 }
20
21 return result;
22};
23
24/**
25 * Splits a string into an array of tokens in the same way the UNIX Bourne shell does.
26 *
27 * @param line A string to split.
28 * @returns An array of the split tokens.
29 */
30export const split = (line: string = "") => {
31 const words = [];
32 let field = "";
33 scan(
34 line,
35 /\s*(?:([^\s\\\'\"]+)|'((?:[^\'\\]|\\.)*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|$)?/,
36 (match) => {
37 const [_raw, word, sq, dq, escape, garbage, separator] = match;
38
39 if (garbage != null) {
40 throw new Error(`Unmatched quote: ${line}`);
41 }
42
43 if (word) {
44 field += word;
45 } else {
46 let addition;
47
48 if (sq) {
49 addition = sq;
50 } else if (dq) {
51 addition = dq;
52 } else if (escape) {
53 addition = escape;
54 }
55
56 if (addition) {
57 field += addition.replace(/\\(?=.)/, "");
58 }
59 }
60
61 if (separator != null) {
62 words.push(field);
63 field = "";
64 }
65 }
66 );
67
68 if (field) {
69 words.push(field);
70 }
71
72 return words;
73};
74
75/**
76 * Escapes a string so that it can be safely used in a Bourne shell command line.
77 *
78 * @param str A string to escape.
79 * @returns The escaped string.
80 */
81export const escape = (str: string = "") => {
82 return str
83 .replace(/([^A-Za-z0-9_\-.,:\/@\n])/g, "\\$1")
84 .replace(/\n/g, "'\n'");
85};