我想在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!
有什么建议吗?
答案 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, "'\\''") + "'" }