Как получить доступ к аргументам командной строки в Swift?


Ответы:


7

Apple выпустила ArgumentParserбиблиотеку именно для этого:

Мы рады анонсировать ArgumentParserновую библиотеку с открытым исходным кодом, которая делает ее простой и даже приятной! - для анализа аргументов командной строки в Swift.

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


Быстрый синтаксический анализатор аргументов

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

Начните с объявления типа, который определяет информацию, которую необходимо собрать из командной строки. Украсьте каждое сохраненное свойство одной из ArgumentParserоболочек свойств и объявите соответствие ParsableCommand.

ArgumentParserБиблиотека разбирает аргументы командной строки, конкретизирует тип команды, а затем либо выполняет свой собственный run()метод или выход с полезным сообщением.


305

Обновление 17.01.17: Обновленный пример для Swift 3. Processбыл переименован в CommandLine.


Обновление 30.09.2015: обновлен пример для работы в Swift 2.


На самом деле это возможно сделать без Foundation или C_ARGV и 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 уже представляет собой массив строк, создавать новую не нужно.
— Lance

9
Практически всегда лучший ответ - не тот, который был принят. :)
— HepaKKes

5
Если кому-то, кроме меня, интересно, Process на самом деле является перечислением .
— robobrobro

1
Такое Process.argumentsже, как NSProcessInfo.processInfo().arguments?
— Франклин Ю

5
В самых последних снимках Swift (снимок от 28 июля или 29 июля) Processобъект теперь известен как CommandLineобъект. Вероятно, это будет полностью включено после официального выпуска Swift 3.0.
— TheSoundDefense


46

Используйте константы верхнего уровня C_ARGCи C_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
Вы также можете использовать NSProcessInfo, как и в Objective-C.
— Джек Лоуренс

3
NSProcessInfo требует Foundation. Мой ответ не требует Foundation. Просто использует стандартную библиотеку swift lang.
— orj 04

7
C_ARCGпохоже, больше не поддерживается.
— juandesant

2
Я могу подтвердить, что C_ARG больше не работает с последней версией инструментов XCode Version 7.1 (7B91b).
— 11

8
Вместо этого вы можете использовать Process.argcи Process.argumentsдля этого, хотя похоже, что это может быть изменено на CommandLine.argcи CommandLine.argumentsс самыми последними изменениями языка.
— TheSoundDefense 08

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

0

Вы можете создать парсер аргументов, используя 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

Проблема с созданием собственного анализатора аргументов заключается в учете всех соглашений об аргументах командной строки. Я бы рекомендовал использовать существующий парсер аргументов.

Вы можете использовать:

  • Модуль консоли Vapor
  • Парсер аргументов TSCUtility, используемый менеджером пакетов Swift
  • Swift Argument Parser с открытым исходным кодом от Apple

Я писал о том, как создавать инструменты командной строки для всех трех. Вы должны проверить их и решить, какой стиль вам больше подходит.

Если вам интересно, вот ссылки:

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.