diff --git a/src/__tests__/index.js b/src/__tests__/index.js index 328c5bf..985df57 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -74,6 +74,23 @@ it(`should handle quoted scripts`, () => { }) }) +it(`should handle escaped characters`, () => { + // this escapes \,",' and $ + crossEnv(['GREETING=Hi', 'NAME=Joe', 'echo \\"\\\'\\$GREETING\\\'\\" && echo $NAME'], { + shell: true, + }) + expect( + crossSpawnMock.spawn, + ).toHaveBeenCalledWith("echo \"'$GREETING'\" && echo $NAME", [], { + stdio: 'inherit', + shell: true, + env: Object.assign({}, process.env, { + GREETING: 'Hi', + NAME: 'Joe', + }), + }) +}) + it(`should do nothing given no command`, () => { crossEnv([]) expect(crossSpawnMock.spawn).toHaveBeenCalledTimes(0) diff --git a/src/index.js b/src/index.js index cddf21a..edad2d9 100644 --- a/src/index.js +++ b/src/index.js @@ -51,8 +51,21 @@ function parseCommand(args) { envSetters[match[1]] = value } else { // No more env setters, the rest of the line must be the command and args - command = args[i] - commandArgs = args.slice(i + 1) + let cStart = [] + cStart = args.slice(i) + // Regex: + // match "\'" or "'" + // or match "\" if followed by [$"\] (lookahead) + .map((a) => { + const re = new RegExp(/(\\)?'|([\\])(?=[$"\\])/, 'g') + // Eliminate all matches except for "\'" => "'" + return a.replace(re, (m) => { + if(m === "\\'") return "'" + return "" + }) + }) + command = cStart[0] + commandArgs = cStart.slice(1) break } }