Como você acessa os argumentos da linha de comando no Swift?


Respostas:


7

A Apple lançou a ArgumentParserbiblioteca para fazer exatamente isso:

Temos o prazer de anunciar ArgumentParser, uma nova biblioteca de código aberto que o torna simples - até mesmo agradável! - para analisar argumentos de linha de comando em Swift.

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


Swift Argument Parser

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

Comece declarando um tipo que define as informações que você precisa coletar da linha de comando. Decore cada propriedade armazenada com um dos ArgumentParserwrappers de propriedade de e declare conformidade com ParsableCommand.

A ArgumentParserbiblioteca analisa os argumentos da linha de comando, instancia seu tipo de comando e, em seguida, executa seu run()método personalizado ou sai com uma mensagem útil.


305

Atualização 17/01/17: Atualizado o exemplo para Swift 3. Processfoi renomeado para CommandLine.


Atualização 30/09/2015: Atualizado o exemplo para funcionar no Swift 2.


Na verdade, é possível fazer isso sem Foundation ou C_ARGV e C_ARGC.

A biblioteca padrão do Swift contém uma estrutura CommandLineque possui uma coleção de Strings chamados arguments. Portanto, você pode ativar argumentos como este:

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 já é um array de strings, não há necessidade de fazer um novo.
Lance

9
Como quase sempre, a melhor resposta não é a aceita. :)
HepaKKes

5
Se alguém além de mim se importa, Processo é na verdade uma enumeração .
robobrobro

1
É Process.argumentso mesmo que NSProcessInfo.processInfo().arguments?
Franklin Yu

5
Nos instantâneos Swift mais recentes (seja o instantâneo 7/28 ou o instantâneo 7/29), o Processobjeto agora é conhecido como o CommandLineobjeto. Isso provavelmente será totalmente incorporado quando o Swift 3.0 for oficialmente lançado.
TheSoundDefense


46

Use as constantes de nível superior 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")
    }
}

Observe que estou usando o intervalo de 1..C_ARGCporque o primeiro elemento da C_ARGV"matriz" é o caminho do aplicativo.

A C_ARGVvariável não é realmente uma matriz, mas pode ser submetida a scripts como uma matriz.


4
Você também pode usar NSProcessInfo, assim como você faz em Objective-C.
Jack Lawrence

3
NSProcessInfo requer Foundation. Minha resposta não requer Fundação. Apenas usa a biblioteca padrão de idioma rápido.
orj

7
C_ARCGparece não ser mais compatível.
2015

2
Posso confirmar que C_ARG não funciona mais com a versão mais recente das ferramentas, XCode versão 7.1 (7B91b).
2015

8
Em vez disso, você pode usar Process.argce Process.argumentspara isso, embora pareça que isso possa estar mudando para CommandLine.argce CommandLine.argumentscom as alterações mais recentes do idioma.
TheSoundDefense

14

Quem quiser usar o antigo "getopt" (que está disponível no Swift) pode usá-lo como referência. Fiz um porte Swift do exemplo GNU em C que pode ser encontrado em:

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

com uma descrição completa. É testado e totalmente funcional. Também não requer Fundação.

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

Você pode criar um analisador de argumento usando o CommandLine.argumentsArray e adicionar qualquer lógica que desejar.

Você pode testar. Crie um arquivoarguments.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)
}

compile e execute:

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

O problema de você construir seu próprio analisador de argumento é levar em consideração todas as convenções de argumento da linha de comando. Eu recomendaria usar um Argument Parser existente.

Você pode usar:

  • Módulo Vapor's Console
  • TSCUtility Argument Parser usado pelo gerenciador de pacotes Swift
  • The Swift Argument Parser com código-fonte aberto da Apple

Eu escrevi sobre como construir ferramentas de linha de comando em todos os três. Você deve verificá-los e decidir qual estilo se adapta melhor a você.

Se você estiver interessado, aqui estão os links:

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.