关于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

相关文章

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

Python UV安装、升级、卸载详细步骤记录

《PythonUV安装、升级、卸载详细步骤记录》:本文主要介绍PythonUV安装、升级、卸载的详细步骤,uv是Astral推出的下一代Python包与项目管理器,主打单一可执行文件、极致性能... 目录安装检查升级设置自动补全卸载UV 命令总结 官方文档详见:https://docs.astral.sh/

统一返回JsonResult踩坑的记录

《统一返回JsonResult踩坑的记录》:本文主要介绍统一返回JsonResult踩坑的记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录统一返回jsonResult踩坑定义了一个统一返回类在使用时,JsonResult没有get/set方法时响应总结统一返回

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

java对接海康摄像头的完整步骤记录

《java对接海康摄像头的完整步骤记录》在Java中调用海康威视摄像头通常需要使用海康威视提供的SDK,下面这篇文章主要给大家介绍了关于java对接海康摄像头的完整步骤,文中通过代码介绍的非常详细,需... 目录一、开发环境准备二、实现Java调用设备接口(一)加载动态链接库(二)结构体、接口重定义1.类型

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

SpringBoot实现文件记录日志及日志文件自动归档和压缩

《SpringBoot实现文件记录日志及日志文件自动归档和压缩》Logback是Java日志框架,通过Logger收集日志并经Appender输出至控制台、文件等,SpringBoot配置logbac... 目录1、什么是Logback2、SpringBoot实现文件记录日志,日志文件自动归档和压缩2.1、

qtcreater配置opencv遇到的坑及实践记录

《qtcreater配置opencv遇到的坑及实践记录》我配置opencv不管是按照网上的教程还是deepseek发现都有些问题,下面是我的配置方法以及实践成功的心得,感兴趣的朋友跟随小编一起看看吧... 目录电脑环境下载环境变量配置qmake加入外部库测试配置我配置opencv不管是按照网上的教程还是de

使用nohup和--remove-source-files在后台运行rsync并记录日志方式

《使用nohup和--remove-source-files在后台运行rsync并记录日志方式》:本文主要介绍使用nohup和--remove-source-files在后台运行rsync并记录日... 目录一、什么是 --remove-source-files?二、示例命令三、命令详解1. nohup2.

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J