Come si accede agli argomenti della riga di comando in Swift?


Risposte:


7

Apple ha rilasciato la ArgumentParserlibreria per fare proprio questo:

Siamo lieti di annunciare ArgumentParser, una nuova libreria open source che lo rende semplice, persino divertente! - per analizzare gli argomenti della riga di comando in Swift.

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


Swift Argument Parser

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

Inizia dichiarando un tipo che definisce le informazioni che devi raccogliere dalla riga di comando. Decora ogni proprietà memorizzata con uno dei ArgumentParserwrapper di proprietà di e dichiara la conformità a ParsableCommand.

La ArgumentParserlibreria analizza gli argomenti della riga di comando, crea un'istanza del tipo di comando e quindi esegue il run()metodo personalizzato o esce con un messaggio utile.


305

Aggiornamento 17/01/17: aggiornato l'esempio per Swift 3. Processè stato rinominato CommandLine.


Aggiornamento 30/09/2015: aggiornato l'esempio per funzionare in Swift 2.


In realtà è possibile farlo senza Foundation o C_ARGV e C_ARGC.

La libreria standard di Swift contiene una struttura CommandLineche ha una raccolta di Strings chiamati arguments. Quindi puoi attivare argomenti come questo:

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 è già un array di stringhe, non è necessario crearne uno nuovo.
Lance

9
Come quasi sempre la risposta migliore non è quella accettata. :)
HepaKKes

5
Se qualcuno oltre a me si preoccupa, Process è in realtà un'enumerazione .
robobrobro

1
È Process.argumentslo stesso di NSProcessInfo.processInfo().arguments?
Franklin Yu

5
Nelle istantanee Swift più recenti (sia l'istantanea del 28/7 che quella del 29/7), l' Processoggetto è ora noto come CommandLineoggetto. Questo sarà probabilmente completamente incorporato una volta che Swift 3.0 sarà ufficialmente rilasciato.
TheSoundDefense


46

Usa le costanti di primo livello C_ARGCe 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")
    }
}

Si noti che sto utilizzando l'intervallo di 1..C_ARGCperché il primo elemento della C_ARGV"matrice" è il percorso dell'applicazione.

La C_ARGVvariabile non è in realtà un array, ma è subscriptable come un array.


4
Puoi anche usare NSProcessInfo, proprio come fai in Objective-C.
Jack Lawrence

3
NSProcessInfo richiede Foundation. La mia risposta non richiede Foundation. Utilizza solo la libreria standard di swift lang.
oppure il

7
C_ARCGsembra non essere più supportato.
juandesant

2
Posso confermare che C_ARG non funziona più con l'ultima versione degli strumenti, XCode versione 7.1 (7B91b).
svth

8
Puoi invece usare Process.argce Process.argumentsper questo, anche se sembra che questo potrebbe cambiare in CommandLine.argce CommandLine.argumentscon le modifiche più recenti alla lingua.
TheSoundDefense

14

Chiunque desideri utilizzare il vecchio "getopt" (disponibile in Swift) può utilizzarlo come riferimento. Ho creato un porting Swift dell'esempio GNU in C che puoi trovare su:

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

con una descrizione completa. È testato e perfettamente funzionante. Non richiede neanche la Fondazione.

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

Puoi creare un parser di argomenti utilizzando CommandLine.argumentsArray e aggiungere la logica che preferisci.

Puoi provarlo. Crea un filearguments.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)
}

compilarlo ed eseguirlo:

$ swiftc arguments.swift
$ ./arguments argument1 argument2 argument3

Il problema con la creazione del proprio analizzatore di argomenti sta prendendo in considerazione tutte le convenzioni degli argomenti della riga di comando. Suggerirei di utilizzare un parser di argomenti esistente.

Potresti usare:

  • Modulo Console di Vapor
  • TSCUtility Argument Parser utilizzato dal gestore dei pacchetti Swift
  • The Swift Argument Parser open-source di Apple

Ho scritto su come creare strumenti da riga di comando su tutti e tre. Dovresti controllarli e decidere quale stile ti si addice meglio.

Se sei interessato ecco i link:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.