在Swift中如何访问命令行参数?

146

在Swift中,如何访问命令行应用程序的命令行参数?


3
可能是如何在Swift中访问程序参数?的重复问题。 - Cœur
6个回答

325

更新01/17/17:已经为Swift 3更新了示例。Process已更名为CommandLine


更新09/30/2015:已将示例更新为适用于Swift 2。


实际上,可以在没有Foundation 或者 C_ARGVC_ARGC的情况下完成这个任务。

Swift标准库包含一个名为CommandLine的结构体,其中有一个名为argumentsString集合。因此,您可以像这样切换参数:

for argument in CommandLine.arguments {
    switch argument {
    case "arg1":
        print("first argument")

    case "arg2":
        print("second argument")

    default:
        print("an argument")
    }
}

11
Process.arguments已经是一个字符串数组,不需要创建新的。 - Lance
10
几乎总是最好的答案并不会被采纳。 :) - HepaKKes
5
如果有人关心的话,"Process" 实际上是一个枚举类型 - robobrobro
1
Process.argumentsNSProcessInfo.processInfo().arguments是相同的吗? - Franklin Yu
5
在最新的Swift快照中(无论是7/28还是7/29快照),Process对象现在被称为CommandLine对象。一旦Swift 3.0正式发布,这可能会被完全整合进去。 - TheSoundDefense
显示剩余4条评论

67

在Swift 3中,请使用CommandLine枚举代替Process

所以:

let arguments = CommandLine.arguments

46

使用顶层常量C_ARGCC_ARGV

for i in 1..C_ARGC {
    let index = Int(i);

    let arg = String.fromCString(C_ARGV[index])
    switch arg {
    case "this":
        println("this yo");

    case "that":
        println("that yo")

    default:
        println("dunno bro")
    }
}

请注意,我使用了1..C_ARGC范围,因为C_ARGV“数组”的第一个元素是应用程序的路径。

C_ARGV变量实际上不是一个数组,但可以像数组一样进行下标操作。


4
你也可以像在Objective-C中一样使用NSProcessInfo。 - Jack Lawrence
3
NSProcessInfo 需要使用 Foundation 框架。我的回答不需要 Foundation,只使用 Swift 标准库。 - orj
7
「C_ARCG」似乎不再受支持。 - juandesant
2
我可以确认,C_ARG在最新版本的工具XCode Version 7.1 (7B91b)中已经不再起作用。 - svth
8
你可以使用 Process.argcProcess.arguments 来替代这个,尽管最近语言的更新似乎将其更改为 CommandLine.argcCommandLine.arguments。请注意不要改变原意。 - TheSoundDefense
显示剩余3条评论

15

苹果公司发布了 ArgumentParser 库,用于处理此类问题:

我们很高兴地宣布 ArgumentParser ,这是一个新的开源库,可使在 Swift 中解析命令行参数变得简单甚至是愉快的。

https://swift.org/blog/argument-parser/


Swift Argument Parser

https://github.com/apple/swift-argument-parser

首先声明一个类型来定义您需要从命令行中收集的信息。对每个存储属性使用 ArgumentParser 的属性包装器之一进行修饰,并声明符合 ParsableCommand 协议。

ArgumentParser 库解析命令行参数,实例化您的命令类型,然后执行自定义的 run() 方法或退出,并提供有用的消息。


14

任何想使用旧的"getopt"(在Swift中可用)的人都可以将此用作参考。我制作了一个Swift版本的GNU C示例,可以在以下链接中找到:

http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html

它带有完整的说明,已测试并且完全功能正常。它也不需要Foundation。

var aFlag   = 0
var bFlag   = 0
var cValue  = String()

let pattern = "abc:"
var buffer = Array(pattern.utf8).map { Int8($0) }

while  true {
    let option = Int(getopt(C_ARGC, C_ARGV, buffer))
    if option == -1 {
        break
    }
    switch "\(UnicodeScalar(option))"
    {
    case "a":
        aFlag = 1
        println("Option -a")
    case "b":
        bFlag = 1
        println("Option -b")
    case "c":
        cValue = String.fromCString(optarg)!
        println("Option -c \(cValue)")
    case "?":
        let charOption = "\(UnicodeScalar(Int(optopt)))"
        if charOption == "c" {
            println("Option '\(charOption)' requires an argument.")
        } else {
            println("Unknown option '\(charOption)'.")
        }
        exit(1)
    default:
        abort()
    }
}
println("aflag ='\(aFlag)', bflag = '\(bFlag)' cvalue = '\(cValue)'")

for index in optind..<C_ARGC {
    println("Non-option argument '\(String.fromCString(C_ARGV[Int(index)])!)'")
}

10
你可以使用 CommandLine.arguments 数组创建一个参数解析器,并添加任何逻辑。
你可以测试它。创建一个名为 arguments.swift 的文件。
//Remember the first argument is the name of the executable
print("you passed \(CommandLine.arguments.count - 1) argument(s)")
print("And they are")
for argument in CommandLine.arguments {
    print(argument)
}

编译并运行它:
$ swiftc arguments.swift
$ ./arguments argument1 argument2 argument3

你自己构建参数解析器的问题在于考虑所有命令行参数惯例。我建议使用现有的Argument Parser。
你可以使用:
- Vapor的Console模块 - Swift Package Manager使用的TSCUtility Argument Parser - Apple开源的Swift Argument Parser 我已经写了关于如何在这三个上构建命令行工具的文章。你应该查看它们并决定哪种风格最适合你。
如果你感兴趣,这里是链接:
- 使用Swift和Vapor的Console模块构建CLI工具 - 使用Swift Package Manager的TSCUtility模块进行命令行参数解析 - 理解Swift Argument Parser并使用STDIN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接