1

我想在JavaScript for Automation (JXA) 中启动一个子进程,并将一个字符串发送到该子进程的标准输入,其中可能包括换行符、shell 元数据等。以前的 AppleScript 方法使用 bash 的<<<运算符、字符串连接和quoted form of字符串。如果有一个quoted form of我可以信任的 JavaScript 等价物来获取所有边缘情况,我可以使用相同的方法;为此,我正在研究正则表达式方法。

但是,我想既然我们可以unistd.h从 JXA 访问,为什么不尝试直接调用$.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!

有什么建议么?

4

3 回答 3

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)
于 2014-12-22T03:16:15.807 回答
1

确实很奇怪,似乎没有与 AppleScript 等效的 JXAquoted 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()评论

据我所知,此实现与以下实现相同quoted form of

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

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

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

于 2015-10-10T06:14:30.910 回答
0

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

我将其更改为似乎可行的:-

// JXA implementation of AppleScript's `quoted form of`
function quotedFormOf(s) { return "'" + s.replace(/'/g, "'\\''") + "'" }
于 2017-02-08T19:09:11.770 回答