夏树正茂

花有重开日,人无再少年.

Swift脚本编辑

| Comments

Swift是一种编译型语言,功能强大而且灵活性十足,现在你甚至可以在shell脚本中运行Swift代码。

编写shell脚本包括以下几个步骤:

  1. 使用编辑器创建脚本。
  2. 设置脚本的权限,使其能够执行。
  3. 执行脚本。

1、编辑脚本

我们可以使用Xcode来直接创建shell脚本:

选择菜单 File -> New -> File,在iOS下选择Other,再在右边选择Shell Script

image

单击Next按钮,将新建的文件保存,命名为SwiftScript,Xcode会自动为其添加.sh的后缀名。这时你就可以在新出现的窗口中编辑脚本了。

Xcode将自动为这个文件添加几行代码,其中最重要的一行是:

#!/bin/sh  

这被称为hash bang语法,指定了要用来运行后续代码行的shell在文件系统中的完整路径。这里指定的是/bin/sh(Bash shell)。进行Swift脚本编程时,需要移除这行代码。事实上,请删除所有这些代码行,并输入如下代码行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env xcrun swift
import Foundation

class Execution {
class func execute(path path: String, arguments: [String]? = nil) -> Int {
   let task = NSTask()
   task.launchPath = path
   if arguments != nil {
     task.arguments = arguments!
   }

   task.launch()
   task.waitUntilExit()
   return Int(task.terminationStatus)

}
}

var status : Int = 0
status = Execution.execute(path: "/bin/ls")
print("Status = \(status)")

status = Execution.execute(path: "/bin/ls", arguments:["/"])
print("Status = \(status)")

该脚本的含义将在稍后介绍。

2、设置权限

脚本是从命令行运行的,所以启动Terminal,进入到你刚才所写shell的文件夹下,执行如下命令:

chmod +x SwiftScript.sh  

它设置脚本文件的权限,使其能够被shell执行。

3、运行脚本

运行脚本很容易,只需要指定脚本的名称,如下:

./SwiftScript.sh  

./是告诉shell,需要执行的脚本位于当前目录中,必须显式地指出这一点,否则shell会找不到脚本。

该脚本运行后,你将看到该shell所在文件夹以及磁盘根文件夹的文件清单,你还将看到Status = 0,它指出用于显示文件命令运行正常,没有出现问题。

4、工作原理

第一行是前面说过的hash bang,这里指定的应用路径为/usr/bin/env,它是一个为shell脚本设置环境的特殊命令,路径后面是一个你很熟悉的命令—启动REPL的命令1

1
  #!/usr/bin/env xcrun swift  

下一条命令是一个import命令,与我们应用程序一样,Swift脚本也需要有基本的代码库才能运行。Foundation是向Swift脚本提供基本功能的框架,因此这里导入它:

import Foundation  

接下来是一个名为ExecutionSwift类,其使命是执行命令,将需要执行的命令封装在类中,后面的执行将容易很多。

class Execution {

}  

这个类中只有唯一的类方法execute,用关键字class定义:一个名为pathString参数(用于指定要运行的可执行文件的路径)以及一个名为argumentsString数组参数(这个参数是可选的,默认值是nil)。这个方法的返回值是一个Int值,指出了命令的执行状态。

execute方法中使用Foundation类的NSTask来设置启动路径和参数:

let task = NSTask()  
task.launchPath = path

对于参数arguments,必须检查其为非nil才能使用!将其解包并赋值给task对象的属性arguments

if arguments != nil {
    task.arguments = arguments!
}

设置好task对象后,调用其launch命令来执行指定的命令:

task.launch()    

有关NSTask的文档指出,必须调用方法waitUntilExit让任务结束。

task.waitUntilExit()  

最后,将task对象的属性terminationStatus作为Int值返回(这个属性的类型为Int32,因此这里将其转换为Int,以方便调用者):

return Int(task.terminationStatus)  

在类定义的后面,定义了一个变量用于存储方法execute方法的返回值:

var status : Int = 0  

接下来,调用execute来执行命令、bin/ls(它显示目录中的文件)。
另外,注意到一开始没有传入参数arguments

status = Execution.execute(path: "/bin/ls")
println("Status = \(status)")

接下来,再次调用方法execute来执行命令/bin/ls,但这次通过参数arguments指定了根路径/

status = Execution.execute(path: "/bin/ls", arguments:["/"])
print("Status = \(status)")  

你可以使用Swift编写一个类,并在Shell脚本中使用。

参考文献:

Swift基础教程


  1. REPL(Read-Eval-Print-Loop)是一个命令行工具,可用于快速尝试Swift代码,在Mac OPX中,可在应用程序Terminal中运行它。

Comments