初识 AppleScript

作者: BenXia | 来源:发表于2018-10-02 23:47 被阅读2779次

    初始 AppleScript

    首先了解一下 Apple 公司创造 AppleScript 的初衷,它是用来编写运行于mac的脚本的。重要的是它是 mac 上操作应用程序为数不多的途径之一。非常方便实现一些平常工作中重复工作的脚本化,提升工作效率,避免重复劳动。

    AppleScript 有啥用?


    • 可以用来书写脚本直接生成脚本文件(.scpt)、App 文件;

    • 可以用来编写 Cocoa App(也可以创建 Automation Action);

    • 可以在 Alfred.app 和 Autormator.app 中使用;

    • 可以非常方便的在 Shell 和 OC 中调用执行;

    AppleScript 编辑器


    MacOS 上有自带的脚本编辑器,目前支持 AppleScript 和 JavaScript。
    其中有模版工程、模版代码、应用词典等功能,极大方便了 AppleScript/JavaScript 脚本的编写。


    1.ScriptEditor.png 2.ScriptEditor.png

    基础语法


    • 基本数据类型

      AppleScript有4种最基本的数据类型:number、string、list和record,分别对应编程概念中的数值、字符串、数组和字典。

      • number 类型

        set x to 2
        get x
        set y to 3
        get y
        set xy to x * y
        set x3 to y ^ 3
        
      • string 类型

        set strX to "Hello "
        set strY to "AppleScript"
        
        -- 字符串拼接
        set strXY to strX & strY
        -- 获取字符串长度
        set lengthOfStrXY to the length of strXY
        
        -- 分割成单个字符并组成一个新的列表
        set charList to every character of strXY
        
        -- 通过 AppleScript's text item delimiters 来指定分隔号,然后通过 every text item of 来实现分割
        set defaultDelimiters to AppleScript's text item delimiters
        set AppleScript's text item delimiters to " "
        set listAfterDelimiter to every text item of strXY
        set AppleScript's text item delimiters to defaultDelimiters
        
        
        -- number 与 string 类型转换
        set numberToString to 100 as string
        set stringToNumber to "1234" as number
        
      • list 类型

        set firstList to { 100, 200.0, "djfif", -10 }
        set emptyList to {}
        set currentList to { 2, 3, 4, 5 }
        
        -- 列表拼接
        set modifiedList to firstList & emptyList & currentList
        
        -- 获取和更改列表中的元素
        set item 2 of modifiedList to "2"
        get modifiedList
        set the third item of modifiedList to "abcde"
        get modifiedList
        
        -- 用列表中的随机元素赋值
        set randomX to some item of modifiedList
        
        -- 获取最后一个元素
        set lastItem to the last item of modifiedList
        
        -- 负数表示从列表尾端开始获取元素
        set aLastItem to item -2 of modifiedList
        
        -- 获取第一个元素
        set firstItem to the first item of modifiedList
        
        set longList to { 1,2,3,4,5,6,7,8,9,10 }
        set shortList to items 6 through 8 of longList
        
        -- 逆向获取子列表
        set reversedList to reverse of longList
        set listCount to the count of longList
        set the end of longList to 5
        get longList
        
        -- 将 string 转换为 list
        set string1 to "string1"
        set stringList to string1 as list
        
        -- 可以用&将字符串和列表连接起来,结果取决于&前面的变量
        set strAndList to string1 & stringList
        
      • record 类型

        set aRecord to { name1:100, name2:"This is a record"}
        set valueOfName1 to the name1 of aRecord
        
        set newRecord to { name1:name1 of aRecord }
        
        set numberOfProperties to the count of aRecord
        
    • 条件/循环

      set x to 500
      
      if x > 100 then
        display alert "x > 100"
      else if x > 10 then
          display alert "x > 10"
      else
          display alert "x <= 10"
      end if
      
      
      set sum to 0
      set i to 0
      repeat 100 times
          set i to i + 1
          set sum to sum + i
      end repeat
      get sum
      
      
      repeat with counter from 0 to 10 by 2
          display dialog counter
      end repeat
      
      set counter to 0
      set listToSet to {}
      -- 注意下这个 ≠ 符号是使用 Option+= 输入的
      repeat while counter ≠ 10
        -- display dialog counter as string
        set listToSet to listToSet & counter
        set counter to counter + 2
      end repeat
      get listToSet
      
      set counter to 0
      set listToSet to {}
      repeat until counter = 10
          -- display dialog counter as string
          set listToSet to listToSet & counter
          set counter to counter + 2
      end repeat
      get listToSet
      
      set aList to { 1, 2, 8 }
      repeat with anItem in aList
          display dialog anItem as string
      end repeat
      
    • 注释

      -- 这是单行的注释
      
      (*
      这是多行的注释
      这是多行的注释
      *)
      
    • 函数

      on showAlert(alertStr)
        display alert alertStr buttons {"I know", "Cancel"} default button "I know"
      end showAlert
      
      showAlert("hello world")
      
    • 换行

      -- 键盘使用组合键 Option+L 输入'¬' 可以实现代码折行
      on showAlert(alertStr)
        display alert alertStr ¬
            buttons {"I know", "Cancel"} default button "I know"
      end showAlert
      
      showAlert("hello world")
      
    • 使用AppleScript中的对话框

      使用弹出框有一些要注意的地方:

      • 1.它可以有多个按钮的;
      • 2.它是有返回值的,返回值是你最终操作的字符串;
      • 3.它是可以增加输入框的,而且比你想的简单多了;
      set dialogString to "Input a number here"
      set returnedString to display dialog dialogString default answer ""
      get returnedString
      //{button returned:"好", text returned:"asdf"}
      
      set dialogString to "Input a number here"
      set returnedString to display dialog dialogString default answer ""
      set returnedNumber to the text returned of returnedString
      try
        set returnedNumber to returnedNumber as number
        set calNumber to returnedNumber * 100
        display dialog calNumber
      on error the error_message number the error_number
        display dialog "Error:" & the error_number & " Details:" & the error_message
      end try
      
      beep
      
    • 预定义变量

      就是一些特殊的关键字,类似于其他语言中的 self、return等,有固定的含义;

      千万不要用它来自定义变量。

      • result:记录最近一个命令执行的结果,如果命令没有结果,那么将会得到错误

      • it:指代最近的一个 tell 对象

      • me:这指代段脚本。用法举例 path to me 返回本脚本所在绝对路径

      • tab:用于string,一个制表位

      • return:用于string,一个换行

    • 字符串比较:Considering/Ignoring语句

      在 AppleScript 的字符串比较方式中,你可以设定比较的方式:上面 considering 和 ignoring 含义都是清晰的,一个用于加上xx特征,一个用于忽略某个特征;一个特征就是一个attribute。
      atrribute应该为列表中的任意一个:

      • case 大小写

      • diacriticals 字母变调符号(如e和é)

      • hyphens 连字符(-)

      • numeric strings 数字化字符串(默认是忽略的),用于比较版本号时启用它。

      • punctuation 标点符号(,.?!等等,包括中文标点)

      • white space 空格

        ignoring case
          if "AAA" = "aaa" then
              display alert "AAA equal aaa when ignoring case"
          end if
        end ignoring
        
        considering numeric strings
          if "10.3" > "9.3" then
              display alert "10.3 > 9.3"
          end if
        end considering
        
    • 列表选择对话框

      display alert "这是一个警告" message "这是警告的内容" as warning
      
      choose from list {"选项1", "选项2", "选项3"} with title "选择框" with prompt "请选择选项"
      

      选择框有以下参数:

      • 直接参数 紧跟list类型参数,包含所有备选项
      • title 紧跟text,指定对话框的标题
      • prompt 紧跟text,指定提示信息
      • default items 紧跟list,指定默认选择的项目
      • empty selection allowed 后紧跟true表示允许不选
      • multiple selections allowed 后紧跟true表示允许多选
    • 文件选择对话框

      -- 选取文件名称Choose File Name
      choose file name with prompt "指定提示信息"
      
      -- 选取文件夹Choose Folder
      choose folder with prompt "指定提示信息" default location file "Macintosh HD:Users" with invisibles, multiple selections allowed and showing package contents
      
      -- 选取文件Choose File
      choose file of type {"txt"}
      
    • 文件读取和写入

      文件读取用read,允许直接读取;

      但是写入文件之前必须先打开文件,打开文件是open for access FileName;

      写入文件用write...to语句;

      最后记得关闭文件close access filePoint

      set myFile to alias "Macintosh HD:Users:xiaxuqiang:Desktop:example.txt"
      read myFile
      set aFile to alias "Macintosh HD:Users:xiaxuqiang:Desktop:example.txt"
      set fp to open for access aFile with write permission
      write "AppleScript写入文本" to fp
      close access fp
      
      
      --在桌面上创建一个文件,内部包含一个txt文件,并向txt内插入文件
      on createMyTxt()
        tell application "Finder"
            make new folder at desktop with properties {name:"star"}
            make new file at folder "star" of desktop with properties {name:"star.txt"}
        end tell
      end createMyTxt
      
      --向txt文件内写入内容
      on writeTextToFile()
        set txtFile to alias "Macintosh HD:Users:xiaxuqiang:Desktop:star:star.txt"
        set fp to open for access txtFile with write permission
        write "你好,这是一个txt文件" to fp as «class utf8»
        close access fp
      end writeTextToFile
      
      createMyTxt()
      
      writeTextToFile()
      
      
      
    • 其它语法

      上面的例子只是苹果官方文档的精简入门版,还有语言的面相对象特征,此处不再展开。

      AppleScript 中还有比较丰富的其它 Command 集合,此处也不再一一列举。

    案例列举


    • 使用 mac 的邮件系统

      --Variables
      set recipientName to " 小红"
      set recipientAddress to "aliyunzixun@xxx.com"
      set theSubject to "AppleScript Automated Email"
      set theContent to "This email was created and sent using AppleScript!"
      --Mail Tell Block
      tell application "Mail"
        --Create the message
        set theMessage to make new outgoing message with properties {subject:theSubject, content:theContent, visible:true}
        --Set a recipient
        tell theMessage
            make new to recipient with properties {name:recipientName, address:recipientAddress}
            --Send the Message
            send
        end tell
      end tell
      
    • 让浏览器打开网页

      set urlMyBlog to "https://blog.csdn.net/sodaslay"
      set urlChinaSearch to "http://www.chinaso.com"
      set urlBiying to "https://cn.bing.com"
      
      --使用Chrome浏览器
      tell application "Google Chrome"
        --新建一个chrome窗口
        set window1 to make new window
        tell window1
            --当前标签页加载必应,就是不用百度哈哈
            set currTab to active tab of window1
            set URL of currTab to urlBiying
            --打开csdn博客,搜索
            make new tab with properties {URL:urlMyBlog}
            make new tab with properties {URL:urlChinaSearch}
            --将焦点由最后一个打开的标签页还给首个标签页
            set active tab index of window1 to 1
        end tell
      end tell
      
      
    • 让你的电脑说话

      -- You can use any of the voices from the System Voice pop-up on the Text to Speech tab in the Speech preferences pane.
      -- Default Value:
      -- The current System Voice (set in the Speech panel in System Preferences.
      
      tell current application
        say "My name is LiMei. Nice to meet you. How are you?" using "Veena"
        say "Fine, thanks. And you?" using "Victoria"
        say "滚"
        say "我跟你说" using "Sin-Ji"
      end tell
      
      beep
      
    • 调用 mac 的通知中心

      crontab + AppleScript + 通知中心 可以做很多定制的提醒工具

      display notification "message" with title "title" subtitle "subtitle"
      
      display notification "message" sound name "Bottle.aiff"
      -- 声音文件都在 ~/Library/Sounds 和 /System/Library/Sounds 下面
      
    • 清理废纸篓

      tell application "Finder"
        empty the trash
        beep
        -- 打开启动磁盘
        open the startup disk
      end tell
      
    • 模拟键盘按键消息

      launch application "System Events"
      launch application "TextMate"
      tell application "System Events"
        set frontmost of process "TextMate" to true
        keystroke "input string from applescript"
        keystroke "a" using command down
        keystroke "c" using command down
        keystroke "a" using command down
        key code 124 using command down
        keystroke "
      "
        keystroke "v" using command down
      end tell
      

      其中 using command 可以使用组合,例如:key code 53 using {command down, option down}

      其中的 key code 对照表如下

      apple key code list:
      
      0 0x00 ANSI_A
      1 0x01 ANSI_S
      2 0x02 ANSI_D
      3 0x03 ANSI_F
      4 0x04 ANSI_H
      5 0x05 ANSI_G
      6 0x06 ANSI_Z
      7 0x07 ANSI_X
      8 0x08 ANSI_C
      9 0x09 ANSI_V
      10 0x0A ISO_Section
      11 0x0B ANSI_B
      12 0x0C ANSI_Q
      13 0x0D ANSI_W
      14 0x0E ANSI_E
      15 0x0F ANSI_R
      16 0x10 ANSI_Y
      17 0x11 ANSI_T
      18 0x12 ANSI_1
      19 0x13 ANSI_2
      20 0x14 ANSI_3
      21 0x15 ANSI_4
      22 0x16 ANSI_6
      23 0x17 ANSI_5
      24 0x18 ANSI_Equal
      25 0x19 ANSI_9
      26 0x1A ANSI_7
      27 0x1B ANSI_Minus
      28 0x1C ANSI_8
      29 0x1D ANSI_0
      30 0x1E ANSI_RightBracket
      31 0x1F ANSI_O
      32 0x20 ANSI_U
      33 0x21 ANSI_LeftBracket
      34 0x22 ANSI_I
      35 0x23 ANSI_P
      36 0x24 Return
      37 0x25 ANSI_L
      38 0x26 ANSI_J
      39 0x27 ANSI_Quote
      40 0x28 ANSI_K
      41 0x29 ANSI_Semicolon
      42 0x2A ANSI_Backslash
      43 0x2B ANSI_Comma
      44 0x2C ANSI_Slash
      45 0x2D ANSI_N
      46 0x2E ANSI_M
      47 0x2F ANSI_Period
      48 0x30 Tab
      49 0x31 Space
      50 0x32 ANSI_Grave
      51 0x33 Delete
      53 0x35 Escape
      55 0x37 Command
      56 0x38 Shift
      57 0x39 CapsLock
      58 0x3A Option
      59 0x3B Control
      60 0x3C RightShift
      61 0x3D RightOption
      62 0x3E RightControl
      63 0x3F Function
      64 0x40 F17
      65 0x41 ANSI_KeypadDecimal
      67 0x43 ANSI_KeypadMultiply
      69 0x45 ANSI_KeypadPlus
      71 0x47 ANSI_KeypadClear
      72 0x48 VolumeUp
      73 0x49 VolumeDown
      74 0x4A Mute
      75 0x4B ANSI_KeypadDivide
      76 0x4C ANSI_KeypadEnter
      78 0x4E ANSI_KeypadMinus
      79 0x4F F18
      80 0x50 F19
      81 0x51 ANSI_KeypadEquals
      82 0x52 ANSI_Keypad0
      83 0x53 ANSI_Keypad1
      84 0x54 ANSI_Keypad2
      85 0x55 ANSI_Keypad3
      86 0x56 ANSI_Keypad4
      87 0x57 ANSI_Keypad5
      88 0x58 ANSI_Keypad6
      89 0x59 ANSI_Keypad7
      90 0x5A F20
      91 0x5B ANSI_Keypad8
      92 0x5C ANSI_Keypad9
      93 0x5D JIS_Yen
      94 0x5E JIS_Underscore
      95 0x5F JIS_KeypadComma
      96 0x60 F5
      97 0x61 F6
      98 0x62 F7
      99 0x63 F3
      100 0x64 F8
      101 0x65 F9
      102 0x66 JIS_Eisu
      103 0x67 F11
      104 0x68 JIS_Kana
      105 0x69 F13
      106 0x6A F16
      107 0x6B F14
      109 0x6D F10
      111 0x6F F12
      113 0x71 F15
      114 0x72 Help
      115 0x73 Home
      116 0x74 PageUp
      117 0x75 ForwardDelete
      118 0x76 F4
      119 0x77 End
      120 0x78 F2
      121 0x79 PageDown
      122 0x7A F1
      123 0x7B LeftArrow
      124 0x7C RightArrow
      125 0x7D DownArrow
      126 0x7E UpArrow
      
    • 切换程序前台、设置焦点窗口

      -- 前提是当前 iTerm app 中打开了两个窗口,其中有个窗口名字叫 "2. bash" 并且该窗口中第一个 tab 中含有三个 session,本脚本的作用是让 "2. bash" 窗口中第一个 tab 中的第三个 session 变为焦点。
      tell the application "iTerm"
        activate
        
        set theWindow to the first item of ¬
            (get the windows whose name is "2. bash")
        if index of theWindow is not 1 then
            set index of theWindow to 1
            
            set visible of theWindow to false
            set visible of theWindow to true
        end if
        
        tell theWindow
            set theTab to the first item of theWindow's tabs
            
            select theTab
            
            select the third session of theTab
        end tell
      end tell
      
      -- 下面是上面的逻辑的另一种实现
      tell the application "iTerm"
        activate
        
        set theWindow to the first item of ¬
            (get the windows whose name is "2. bash")
        if the index of theWindow is not 1 then
            set the index of theWindow to 2
            tell application "System Events" to ¬
                tell application process "iTerm2" to ¬
                    keystroke "`" using command down
        end if
      end tell
      
    • 粘贴板操作

      set the clipboard to "Add this sentence at the end."
      tell application "TextEdit"
        activate --make sure TextEdit is running
        make new paragraph at end of document 1 with data (return & (the clipboard))
      end tell
      

    上面的例子都是一些比较简单的例子,还有很多有趣的例子可以自己根据需要,查询词典中涉及到的 App 的 AppleScript 接口自己做实现。关于如何使用 App 的 AppleScript 的词典,建议阅读Mac 的自动化 AppleScript 终极入门手册

    何时使用?


    • 一些跨应用的重复操作步骤使用 AppleScript/JavaScript 实现关键步骤
    • 结合 Alread.app、Automator.app、crontab 等实现一些场景的触发调用
    • 本地的一些工具脚本可以直接调用 AppleScript 做一些简单的输入、弹框、通知交互
    • 用 AppleScript 写一个 CocoaApp 或者 Automator Action(但是可以用 Objective-C 我们就没必要使用相对不熟悉的 AppleScript
    • OC 的命令行工程可以借助 NSAppleScript 操作其它应用
    • CocoaApp 工程可以通过 XPCService+ScriptingBridge+AppleScript(OC版本接口调用)启动其它应用(样例工程)

    生成 Cocoa App 的 OC 接口文件


    需要通过 OC 调用系统中某个 App 的接口,可以参照如下命令行导出其 .h 文件

    sdef /Applications/Mail.app | sdp -fh -o ~/Desktop --basename Mail --bundleid `defaults read "/Applications/Mail.app/Contents/Info" CFBundleIdentifier`
    

    更多资料


    AppleScript Language Guide 官方文档

    Mac Automation Scripting Guide

    AppleScript 与 Shell 的互相调用

    Objective-C 运行 AppleScript 脚本

    如何让 Cocoa App 支持 AppleScript

    AppleScript for Absolute Starters

    Apple Automator with AppleScript

    JavaScript for Automation

    JXA-Cookbook

    相关文章

      网友评论

        本文标题:初识 AppleScript

        本文链接:https://www.haomeiwen.com/subject/cjzaoftx.html