【问题标题】:Encapsulating one-line AppleScript with C system() call using fgets() and echo使用 fgets() 和 echo 用 C system() 调用封装单行 AppleScript
【发布时间】:2013-01-25 00:36:13
【问题描述】:

如果我将 AppleScript 压缩为一行,我如何将其封装在 C 程序的 echo system 调用中运行?我尝试过的所有格式都会导致错误:(单引号、双引号、各种括号等...)

如果不清楚,我有一个 C 程序,它使用 fgets() 来捕获输入。当我尝试在系统命令中回显时,例如echo ' && foo bar && $? ' 它通常可以工作。但是,如果我想直接在 AppleScript 中 echo,我似乎无法降低格式。有什么想法吗?

FWIW 这是我正在尝试的:

echo ' && "osascript -e 'tell application "Terminal"' -e 'do script "foo bar"' -e 'end tell'" && $?'

上面的示例回显了单引号中包含的所有内容并“打印”它,但不执行它。我尝试了许多关于报价的变体等,但无济于事。此外,osascript ... 'end tell' 之间直接在终端中运行时有效。

感谢任何帮助!

编辑

这是 C 代码的 sn-p:

    char comment[80];
    char cmd[120];
    fgets(comment, 80, stdin);
    sprintf(cmd, "echo '%s %s' >> reports.log", comment, now());
    system(cmd);

编辑两个...更改标题以更准确

【问题讨论】:

  • 你能发布一个可运行的例子而不是foo bar吗?
  • 当然。几乎任何 bash 脚本都可以运行似乎...echo ' && pwd && $? ' 是一个可以通过我的 C 程序运行的简单脚本。同样,echo && pwd && $? 直接在终端中工作。
  • @JoshCaswell 哦,对于 AppleScript,这样的东西将在终端中运行:echo && osascript -e 'tell application "Terminal"' -e 'do script "pwd"' -e 'end tell' ...显然我无法通过程序使用 echo
  • 你是如何将它包含在你的 C 代码中的?

标签: c macos scripting terminal applescript


【解决方案1】:

好的!根据您的 cmets,我将您的问题改写如下:

如何欺骗system("echo %s") 运行AppleScript?

我正在尝试突破system() 的极限以了解它的原因 重要的是要小心它在 C 中的使用。这个示例程序是 在一本关于 C 的书中介绍:

#include <stdio.h>
#include <stdlib.h>

char* now() {
    return "yyyy-mm-dd";
}

int main() {
    char comment[80];
    char cmd[120];
    fgets(comment, 80, stdin);
    sprintf(cmd, "echo '%s %s' >> reports.log", comment, now());
    return system(cmd);
}

我可以“回显”程序并使用以下命令执行大多数 bash 脚本 通过键入' &amp;&amp; pwd &amp;&amp; ' 进行编程。现在我想弄清楚该怎么做 类似的东西,但使用 AppleScript 而不是 bash。我是 试试这个:

' && "osascript -e 'tell application "Terminal"' -e 'do script "foo bar"' -e 'end tell'" && '

osascript ... 'end tell' 命令直接在 终端,但它没有正确执行。我试过很多 报价等的变化无济于事。

那么,我的回答如下:


为了更容易准确地调试正在运行的命令,让我们将命令回显到终端:

#include <stdio.h>
#include <stdlib.h>

char* now() {
    return "yyyy-mm-dd";
}

int main() {
    char comment[80];
    char cmd[120];
    fgets(comment, 80, stdin);
    sprintf(cmd, "echo '%s %s' >> reports.log", comment, now());

    /* for debugging */
    printf("executing %s\n", cmd);

    return system(cmd);
}

现在让我们试试吧:

$ gcc -c prog.c -o prog
$ ./prog
' && osascript -e 'tell application "Terminal"' -e 'do script "date"' -e 'end tell'" && '
executing echo '' && osascript -e 'tell application "Terminal"' -e 'do script "date"' -e 'end t yyyy-mm-dd' >> reports.log

嗯!它以某种方式被切断为end t 而不是end tell'" &amp;&amp; '。等等,输入缓冲区有多大? 80 个字符?那就是问题所在!您尝试的 AppleScript 命令在语法上是正确的,但对于输入缓冲区来说太长并且被截断了。

消除所有空格并使用 little-known bash feature 嵌入换行符,我几乎可以将 AppleScript 压缩为 77 个字符:

'&&osascript -e$'tell application "Terminal"\ndo script "date"\nend tell'&& '

由于 80 个字符的缓冲区最后需要一个空终止符,它实际上只有 79 个字符的空间。因此,使用这个特殊的 AppleScript 命令,您可以在终端中运行最长 6 个字符的 shell 命令……


我对您最初的问题的回答——如何从 C 调用多行 AppleScript——仍然是:


命令行参数可以包含换行符。您可以像这样从 bash 运行整个 AppleScript:

$ osascript -e '
tell application "Terminal"
    do script "date"
end tell'

bash 暂停等待关闭 ',然后将整个脚本作为单个参数传递。

你可以在 C 中做类似的事情,只是多引用一点:

#include <stdio.h>

int main() {
    system("osascript -e '\n"
            "tell application \"Terminal\"\n"
            "   do script \"date\"\n"
            "end tell'\n");
    return 0;
}

【讨论】:

  • fgets() 提供的灵活性相当方便——我可以在同一个程序中传递多个 bash 参数。虽然重新编写我的程序以格式化输入然后将其作为system() 调用发送绝对是可能的,但我希望有一个简单的解决方案将AppleScript 封装在echo 中,就像我能够为bash 和@987654340 一样@...你知道用echo 捕获AppleScript 的方法吗?就像我可以为bash 命令捕获的一样?
  • 很抱歉,我无法准确理解您要执行的操作。您是否只是想将commentfgets() 和时间戳附加到reports.log?为此,您可以执行 FILE* reports = fopen("reports.log", "a"); fprintf(reports, "%s %s\n", comment, now()); fclose(reports); 并完全跳过 system()echo
  • 不,我试图突破system() 的极限,以了解为什么在 C 中谨慎使用它很重要。这个练习在一本关于 C 的书中介绍。我可以“ echo out" 并使用该程序执行大多数 bash 脚本,我想弄清楚如何做类似的事情,但使用 AppleScript 而不是 bash。因此,bash 工作和 AppleScript 不工作的各种示例。 基本问题——在这一点上——是如何通过终端输入将 AppleScript 封装到 fgets() 中,以便我可以回显到终端并执行 AppleScript。
  • 这更清楚了:这本书有一个“滥用”system() 的练习,以了解如何在 C 编程中小心使用它。当程序通过fgets() 请求输入时,我可以使用类似于上述示例之一的方法“回显”该程序。但是,我只能使用 bash 命令成功地做到这一点。我很好奇它是否可以用 AppleScript 来完成,这需要将 AppleScript 封装到 fgets()、system()、echo 等中。我无法得到以这种方式执行 AppleScript 的回声,但是可以直接将 AppleScript 回显到来自~$的终端...
  • ... 所以我认为这只是一个语法错误,因为我必须用单引号捕获“回显”,我认为这与 AppleScript 中单引号的使用相冲突。至少,这是我的猜测。
猜你喜欢
  • 1970-01-01
  • 2019-01-06
  • 2010-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多