Як ви отримуєте доступ до аргументів командного рядка в 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.


Насправді це можливо зробити без фонду чи C_ARGV та C_ARGC.

Стандартна бібліотека Swift містить структуру, CommandLineяка має колекцію Strings 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
Якщо хтось, окрім мене, дбає, Процес насправді є перерахуванням .
robobrobro

1
Це Process.argumentsте саме, що NSProcessInfo.processInfo().arguments?
Франклін Ю

5
В останніх знімках Swift (знімок 7/28 або знімок 7/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 вимагає створення фонду. Моя відповідь не потребує фонду. Просто використовує швидкий стандартний лінг.
orj

7
C_ARCGсхоже, більше не підтримується.
Джундесант

2
Я можу підтвердити, що C_ARG більше не працює з останньою версією інструментів, XCode версії 7.1 (7B91b).
svth

8
Натомість можна використовувати Process.argcі Process.argumentsдля цього, хоча, схоже, це може бути змінено на CommandLine.argcта CommandLine.argumentsз останніми змінами мови.
TheSoundDefense

14

Кожен, хто хоче використовувати старий "getopt" (який доступний у Swift), може використовувати це як довідку. Я зробив порт Swift з прикладу GNU в C, який можна знайти за адресою:

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

з повним описом. Це перевірено і повністю функціональне. Він також не потребує фонду.

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
  • Швидкий аналізатор аргументів Apple відкритий джерелом Apple

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

Якщо ви зацікавлені тут, перейдіть за посиланнями:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.