管道到JXA的子进程stdin

时间:2014-12-21 04:18:49

标签: macos osx-yosemite javascript-automation jxa

我想在JavaScript for Automation(JXA)中启动一个子进程并向该子进程的stdin发送一个字符串,其中可能包括换行符,shell metas等。以前的AppleScript方法用于这个用过的bash的<<<运算符,字符串连接,以及quoted form of字符串。如果有一个等价的JavaScript quoted form of我可以信任以获得所有边缘情况,我可以使用相同的方法;我正在研究这方面的正则表达式方法。

但是,我认为既然我们可以从JXA访问unistd.h,为什么不尝试直接拨打$.pipe$.fork$.execlp$.pipe看起来应该使用2个整数的数组作为参数,但我尝试过的所有东西都不起作用:

ObjC.import('unistd')
$.pipe() // Error: incorrect number of arguments
$.pipe([]) // segfault
$.pipe([3,4]) // segfault
$.pipe([$(), $()]) // segfault
var a = $(), b=$()
$.pipe([a,b]) // segfault
$.pipe($([a,b])) // NSException without a terribly helpful backtrace
$.pipe($([$(3), $(4)])) // segfault
var ref = Ref('int[2]')
$.pipe(ref)
ref[0] // 4, which is close!

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

我找到了一种方法,使用Cocoa而不是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)

答案 1 :(得分:0)

确实很奇怪似乎没有JXA相当于AppleScript的quoted form of来安全地将脚本文字传递给shell命令。

但是,实施相当容易:

// 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'|\"")))

quotedForm()的信用额转到this comment

据我所知,此实现与quoted form of的做法相同:

  • 在最简单的形式中,如果字符串不包含嵌入的单引号,则单引号整个字符串;由于类似POSIX的shell在单引号字符串上不执行任何插值,因此它保持原样。

  • 如果字符串 包含嵌入的单引号,则会将其有效地分解为多个单引号字符串,每个嵌入的单引号都拼接为\'(反斜杠转义) - 这是必要的,因为无法在POSIX兼容shell中的单引号文字中嵌入单引号。

在兼容POSIX的shell中,这适用于所有字符串。

答案 2 :(得分:0)

上面的quotedForm函数(下面的?)缺少一个非常重要的特性,它只引用/转义第一个内联撇号,而它需要处理字符串中存在的许多内容。

我把它改成了这个似乎有用的东西: -

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