Pipe to subprocess stdin for JXA

南楼画角 提交于 2019-12-07 01:58:29

I found an approach that works, using Cocoa instead of stdio:

ObjC.import('Cocoa')
var stdin = $.NSPipe.pipe
var stdout = $.NSPipe.pipe
var task = $.NSTask.alloc.init
task.launchPath = "/bin/cat"
task.standardInput = stdin
task.standardOutput = stdout

task.launch
var dataIn = $("foo$HOME'|\"").dataUsingEncoding($.NSUTF8StringEncoding)
stdin.fileHandleForWriting.writeData(dataIn)
stdin.fileHandleForWriting.closeFile
var dataOut = stdout.fileHandleForReading.readDataToEndOfFile
var stringOut = $.NSString.alloc.initWithDataEncoding(dataOut, $.NSUTF8StringEncoding).js
console.log(stringOut)

The quotedForm function above (below?) is lacking one very important feature, it only quotes/escapes the first in-line apostrophe whereas it needs to deal with however many exist in the string.

I changed it to this which seems to work:-

// JXA implementation of AppleScript's `quoted form of`
function quotedFormOf(s) { return "'" + s.replace(/'/g, "'\\''") + "'" }

It is indeed curious that there appears to be no JXA equivalent of AppleScript's quoted form of for safely passing script literals to shell commands.

However, it is fairly easy to implement:

// JXA implementation of AppleScript's `quoted form of`
function quotedForm(s) { return "'" + s.replace(/'/g, "'\\''") + "'" }

// Example
app = Application.currentApplication();
app.includeStandardAdditions = true;

console.log(app.doShellScript('cat <<<' + quotedForm("foo$HOME'|\"")))

Credit for quotedForm() goes to this comment.

As far as I can tell, this implementation does the same as quoted form of does:

  • In the simplest form, if the string contains no embedded single-quotes, it single-quotes the entire string; since POSIX-like shells perform no interpolation whatsoever on a single-quoted string, it is preserved as-is.

  • If the string does contain embedded single-quotes, it is effectively broken into multiple single-quoted strings, with each embedded single-quote spliced in as \' (backslash-escaped) - this is necessary, because it is not possible to embed single-quotes in single-quoted literal in POSIX-compatible shells.

In a POSIX-compatible shell, this should work for all strings.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!