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


Answers:


7

苹果已经发布了ArgumentParser用于执行此操作的库:

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

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


迅捷参数解析器

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

首先声明一个类型,该类型定义您需要从命令行收集的信息。使用ArgumentParser的属性包装器装饰每个存储的属性,并声明与的一致性ParsableCommand

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


305

更新01/17/17:更新了Swift 3的示例,Process已重命名为CommandLine


2015年9月30更新:更新了示例,使其可在Swift 2中使用。


实际上,没有Foundation C_ARGV and 也可以这样做C_ARGC

Swift标准库包含一个结构CommandLine,该结构具有的集合,String称为arguments。因此,您可以打开这样的参数:

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

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

    default:
        print("an argument")
    }
}

10
@AlbinStigo Process.arguments已经是一个字符串数组,无需创建一个新的字符串。
兰斯

9
几乎总是最好的答案不是公认的答案。:)
HepaKKes

5
如果除我之外还有其他人在乎,Process实际上是一个枚举
robobrobro

1
Process.arguments一样的NSProcessInfo.processInfo().arguments吗?
富兰克林于

5
在最新的Swift快照(7/28快照或7/29快照)中,该Process对象现在称为CommandLine对象。Swift 3.0正式发布后,这可能会完全合并。
TheSoundDefense


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。
杰克·劳伦斯

3
NSProcessInfo需要Foundation。我的答案不需要Foundation。只使用swift lang标准库。
orj 2014年

7
C_ARCG似乎不再受支持。
juandesant

2
我可以确认C_ARG不再与最新版本的工具XCode Version 7.1(7B91b)一起使用。
svth 2015年

8
您可以改用Process.argcProcess.arguments为此,尽管看起来这可能正在更改为该语言,CommandLine.argc并且CommandLine.arguments最近更改了该语言。
TheSoundDefense

14

任何想要使用旧的“ getopt”(在Swift中可用)的人都可以将此用作参考。我在C语言中制作了GNU示例的Swift端口,可以在以下位置找到:

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)])!)'")
}

0

您可以使用CommandLine.argumentsArray 创建参数解析器,然后添加所需的任何逻辑。

你可以测试一下。建立档案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

建立自己的参数解析器的问题是考虑了所有命令行参数约定。我建议使用现有的参数解析器。

您可以使用:

  • 蒸气的控制台模块
  • Swift Package Manager使用的TSCUtility参数解析器
  • Apple开源的Swift Argument Parser

我已经写过关于如何在这三个平台上构建命令行工具的文章。您应该检查一下它们,然后确定哪种样式最适合您。

如果您对此感兴趣,请访问以下链接:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.