关于AppleScript一些记录

2023-11-02 22:21
文章标签 记录 applescript

本文主要是介绍关于AppleScript一些记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://bukkake.iteye.com/blog/828322


文中资料来源主要是《AppleScript跟我学》的中文译本以及Apple的的Technical Note

 

AppleScript是用在MacOSX上的脚本语言,和操作系统结合的相当紧密,不过一般来说我也没兴趣学一门应用不太广泛的专属语言,但一来是项目需要,而且这个语言确实好用并且简单易学,就当消遣消遣好了。写好的脚本可以用NSTask很方便的执行,而脚本本身几乎什么都能做。

 

编辑器可以选择自带的Apple Script Editor就在应用程序的实用工具下面,应付是绝对够了,需要代码提示的话请把偏好设置中的“使用脚本助理”勾选,而代码提示的输入是用Esc键,当然你也可以选择Xcode,它也可以创建AppleScript文件,代码提示什么的也比较习惯,不过本着轻松的态度,我还是使用自带的。

 

打开AppleScript编辑器,面板很简单,左上角是四个主要按键,录制,停止,运行,编译。录制什么的我还没用过,停止自然不用说,编译其实也无所谓,因为你在点运行的时候会先编译的。中间是编码框,当然是用来输入脚本的,最下面是描述与系统日志的输出,不做录制的话一般我们只需要关心系统日志的结果就行了。

 

既然是脚本语言嘛,语法什么的根本不要学,直接照着例子来,最简单的,让系统嗡鸣一下就是

 

Applescript代码   收藏代码
  1. beep  

 敲完了之后点一下运行就会执行了,编写代码的时候对于关键字等非引号内部的字符不需要在意大小写,反正运行和保存的时候会帮你格式化好。

你还可以发声,使用say命令,不过可能因为我的机器是黑苹果的缘故,始终报-241的错。

 

再复杂一点,清空废纸篓,这个时候你需要调用finder了

 

Applescript代码   收藏代码
  1. tell application "Finder"  
  2.       empty the trash  
  3. end tell  

 这里tell application是呼唤程序,后续的的程序都必须写在引号里,中间包夹的自然是要这个程序做什么,最后end tell表示对这个程序调用结束。empty the trash是finder专属的操作,除了the之外其他都是背语法也没法实现的。实际上引号里的finder仍然不区分大小写。

如果对这段程序稍加修改

 

Applescript代码   收藏代码
  1. tell application "Finder"  
  2.       beep  
  3.       empty the trash  
  4. end tell  
  5. beep  
  6. open the startup disk  

 很明显,tell到end tell中所有操作都默认主语是"Finder",不过对于系统功能,AppleScript还是能区分出其主语的,但如果把应用程序的操作写到了tell外面,那么就不知道如何进行了,当然根据脚本语言特性,第二个beep还是能执行的。而且编辑器的语法检测也还凑合,如果把empty the trash写在外面,直接语法关都过不去。

 

除了这些照书抄的标准外,项目中用到最多的其实还是其可以直接调用shell的特性,一句话就完事

 

Applescript代码   收藏代码
  1. do shell script "ps A"  

 毫无疑问shell本身也是去找应用程序的,但这么一来无疑轻松多了,有一点需要格外注意,AppleScript的默认shell是/bin/sh而我们用的终端则是/bin/bash,可能会出现在终端中可以执行,但脚本中却说找不到命令的情况,遗憾的是我并没有遇到过。

本段有待补全。。。。。。

 

 

令人惊喜的是,内置的编辑器还可以直接将脚本保存为脚本包或者应用程序,这确实方便了许多。保存为应用程序的时候首先腰进行语法检测,而一旦保存完毕之后,就可以将其添加到登录项(在系统偏好设置-帐户-登录项)里了,开机启动就是如此简单。保存的时候注意没有特别想法不要选中run-only这样会导致你的脚本文件无法编辑了。

 

内置编辑器令人惊奇的地方还不止这些,它还有和Mac上一贯优异的可操作性,比如你完全不必输入长长的application,只要在合适的地方写app,要么用代码提示的自动输入,甚至不用代码提示,在编辑器保存或者编译的时候,它会自动将其补全。除了关键字之外,即使是应用程序也可以方便的替换,比如写

Applescript代码   收藏代码
  1. tell application "shit"  

 这个shit如果计算机上找不到,那么在编译期会跳出窗口让你选择这个shit所代表的程序,并且替换,而且在后续的编写中,你一直使用shit的话,当再次编译时,不需要提示就会自动替换为刚才选择的程序,这个特性在下次打开编辑器的时候仍然保持。你还可以在代码编辑器按下ctrl健后按鼠标,就会出现整理好的很多快捷模块,自己选择就可以,更方便的是你可以先选中一段代码,然后在选贼快捷模块,那么选中的代码就会自动添加到快捷模块内部。

 

接下来是编程语言都有的变量,自然变量都是没有类型的,我猜。定义变量使用set,变量名规则与c类似

Applescript代码   收藏代码
  1. set pitcturPath to "/documents"  

 一旦定义,就可以在后续文本中使用该变量,而且该变量本身也可以修改,而且就代码看来更符合普通人的认识

Applescript代码   收藏代码
  1. set DDd to 100  
  2. set DDd to "dajiahao"  
  3. set aaa to DDd  
  4. display dialog aaa  
  5. display dialog DDd  
  6. set DDd to 100  
  7. display dialog aaa  
  8. display dialog DDd  

 display dialog会用一个对话框显示输出,如果觉得比较烦人也可以直接看编辑器的结果区,不过它仅能显示最后一段代码的结果,即使是set语句也是有结果的,结果就是set的具体值,而且显示的时候还会特地区分字符串和数字,如果是字符串会加上引号。最特别的是如果你按下了对话框的取消按钮,脚本将不会继续执行下去。

+-*/^等操作符不必自然多说,但注意虽然变量无类型,但也不能对字符串进行加减乘除操作,如果需要拼接字符串使用&,可以用于字面值和变量指尖。字符串长度用the length of,字符串内部对引号的转移是常见的前面加反斜杠即\,自然的,你想在字符串里输入一个字面值的反斜杠就要连续输入两个反斜杠。和js类似,如果写"12"-3,那么会自动将"12"转为数值最后得到9.如果想要明确的转型,那么就要使用as

Applescript代码   收藏代码
  1. set abc to "12" as number  
  2. set def to 12 as string  
 

和现代脚本语言Python类似,AppleScript的list也非常简单,用大括号括起来就行了,比如{1,2,3,4},也类型也未必一致如{1,"2",3,4},直接用还是赋值都非常方便,下面是修改展示对话框的按钮的方法

 

Applescript代码   收藏代码
  1. set stringToBeDisplay "dajiahao"  
  2. display dialog stringToBeDisplay buttons{"hello""welcome""goaway"} default button "hello"  

 default button后面可以不用字符串而直接用下标,不过可能它面向的编程人员不同,下标是以1开始的,所以这里得写成default button 3。set i to 100

 

list的连结也很方便,和字符串一样用&就可以了

 

Applescript代码   收藏代码
  1. set firstList to {1}  
  2. set secondList to {23}  
  3. set thirdList to {4}  
  4. set fourthList to firstList & secondList & thirdList  

 那么fourthList就是{1,2,3,4}

其他关于list的东西不想照抄了,这里还是先讲讲程序里如何调用这些脚本

 

首先我们可以用NSAppleScript类直接运行脚本,可以用源码也可以用文件形式,文件可以是源码形式也可以是编译好的。

脚本文件demo.applescript

Applescript代码   收藏代码
  1. set i to 100  

 根据之前的介绍,这里的脚本值就是100

 

Objective-c代码   收藏代码
  1. NSAppleEventDescriptor *eventDescriptor = nil;  
  2. NSAppleScript *script = nil;  
  3. NSBundle *bunlde = [NSBundle mainBundle];  
  4. NSString *scriptPath = [bunlde pathForResource:@"demo"   
  5.                                                                ofType:@"scpt"   
  6.                                                         inDirectory:nil];  
  7. if (scriptPath)  
  8. {  
  9.     script = [[NSAppleScirpt alloc] initWithContentsOfURL:[NSURL fileURLWithPath:scriptPath] error:nil];  
  10.     if (script)  
  11.     {  
  12.         eventDescriptor = [script executeAndReturnError:nil];  
  13.         if (eventDescriptor)  
  14.         {  
  15.             NSLog(@"%@", [eventDescriptor stringValue]);  
  16.         }  
  17.     }  
  18. }  

 没做任何校验,最低安全级别的代码,总之就是这样,如果返回的是list的话,则还要更加麻烦一点

 

Objective-c代码   收藏代码
  1. NSAppleEventDescriptor *e = [NSTask gtm_runAppleScript:@"value"];  
  2. int count = [e numberOfItems];  
  3. for (int i = 1; i <= count; i++)  
  4. {  
  5.     NSAppleEventDescriptor *d = [e descriptorAtIndex:i];  
  6.     NSLog(@"%@", [d stringValue]);  
  7. }  

 和之前提到的一样,下标以1开始。

 

若返回的是record形式的结果,那么就要比list再加一层,假设脚本是这样的

Applescript代码   收藏代码
  1. {key1:1, key2:2, key3:3}  

 所谓的加一层就是这个意思,第一次按下标获取描述符是record的个数,然后再对record里具体条目进行处理,item数值为条目数x2,前一个item是key,后一个item是对应的value

Applescript代码   收藏代码
  1. NSAppleEventDescriptor *e = [NSTask gtm_runAppleScript:@"value"];  
  2. // 其实就返回一个record的话,count就是1  
  3. int count = [e numberOfItems];  
  4. for (int i = 1; i <= count; i++)  
  5. {  
  6.     NSAppleEventDescriptor *d = [e descriptorAtIndex:i];  
  7.     // 这里会是6条  
  8.     int items = [d numberOfItems];  
  9.     NSMutableDictionary *dic = [NSMutableDictionary dictionary];  
  10.     for (int j = 1; j <= items; j +=2)  
  11.     {  
  12.         // 前一条是key的名字  
  13.         NSAppleEventDescriptor *dKey = [d descriptorAtIndex:j];  
  14.         NSString *key = [dKey stringValue];  
  15.        // 后一条是对应的值  
  16.         NSAppleEventDescriptor *dValue = [d descriptorAtIndex:j+1];  
  17.         NSString *value = [dValue stringValue];  
  18.         [dic setObject:value forKey:key];  
  19.     }  
  20. }  
 

 

如果根本不在意返回值,而是仅仅要执行一段脚本,也可以用NSTask,而且还有个问题就是如果想要给脚本传参数的话,之前提到的方法就只能靠自己修改脚本拼接了,想泛用的话还得改脚本,而且此时仅可使用NSTask,可以查阅到NSAppleScript根本没有运行时带参数的方法,假设文件为demo2.applescript

 

Applescript代码   收藏代码
  1. on run{para1, para2}  
  2.     log para1  
  3.     log para2  
  4. end run  

 

 那么代码就要写成这样

 

Objective-c代码   收藏代码
  1. NSTask *task = nil;  
  2. NSBundle *bunlde = [NSBundle mainBundle];  
  3. NSString *scriptPath = [bunlde pathForResource:@"demo2"   
  4.                                                                ofType:@"scpt"   
  5.                                                         inDirectory:nil];  
  6. if (scriptPath)  
  7. {  
  8.     NSArray *a = [NSArray arrayWithObjects:@"fuck", @"you", nil];  
  9.     task = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/osascript"  
  10.                                                          arguments:a];      
  11. }  
  12. return task;  

 所以我很头疼一点,如果又要有参数,又要有返回值那要如何处理。

 

AppleScript很方便的就是可以直接运行shell的源码或者shell文件,简单的使用do shell script即可,不过要注意sh文件的权限问题,否则会出现把sh文件在bash里运行ok,可AppleScript编辑器里却显示Permission denied的问题。

这篇关于关于AppleScript一些记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/333695

相关文章

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Spring Boot中定时任务Cron表达式的终极指南最佳实践记录

《SpringBoot中定时任务Cron表达式的终极指南最佳实践记录》本文详细介绍了SpringBoot中定时任务的实现方法,特别是Cron表达式的使用技巧和高级用法,从基础语法到复杂场景,从快速启... 目录一、Cron表达式基础1.1 Cron表达式结构1.2 核心语法规则二、Spring Boot中定

国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)

《国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)》本文给大家利用deepseek模型搭建私有知识问答库的详细步骤和遇到的问题及解决办法,感兴趣的朋友一起看看吧... 目录1. 第1步大家在安装完ollama后,需要到系统环境变量中添加两个变量2. 第3步 “在cmd中

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板