好的!根据您的评论,我将您的问题改写如下:
如何欺骗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);
}
我可以“回显”程序并通过键入' && pwd && '
. 现在我想弄清楚如何做类似的事情,但使用 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'" && '
. 等等,输入缓冲区有多大?80个字?那就是问题所在!您尝试的 AppleScript 命令在语法上是正确的,但对于输入缓冲区来说太长并且被截断了。
消除所有空格并使用鲜为人知的 bash 功能嵌入换行符,我几乎可以将 AppleScript 压缩为 77 个字符:
'&&osascript -e$'tell application "Terminal"\ndo script "date"\nend tell'&& '
由于 80 个字符的缓冲区最后需要一个空终止符,它实际上只有 79 个字符的空间。因此,使用这个特殊的 AppleScript 命令,您可以在终端中运行最长 6 个字符的 shell 命令……</p>
我对我认为是您最初的问题的回答——如何从 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;
}