Bagaimana Anda mengakses argumen baris perintah di Swift?

Jawaban:

7

Apple telah merilis ArgumentParserperpustakaan untuk melakukan ini:

Kami dengan senang hati mengumumkan ArgumentParser, perpustakaan sumber terbuka baru yang membuatnya mudah - bahkan menyenangkan! - untuk mengurai argumen baris perintah di Swift.

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


Parser Argumen Cepat

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

Mulailah dengan mendeklarasikan tipe yang mendefinisikan informasi yang perlu Anda kumpulkan dari baris perintah. Hiasi setiap properti yang disimpan dengan salah satu ArgumentParserpembungkus properti, dan nyatakan kesesuaian ParsableCommand.

The ArgumentParserperpustakaan mengurai argumen baris perintah, instantiates ketik perintah Anda, dan kemudian mengeksekusi kustom Anda run()metode atau keluar dengan pesan yang bermanfaat.

pkamb
sumber
305

Pembaruan 01/17/17: Memperbarui contoh untuk Swift 3. Processtelah diubah namanya menjadi CommandLine.


Pembaruan 09/30/2015: Memperbarui contoh untuk bekerja di Swift 2.


Sebenarnya mungkin untuk melakukan ini tanpa Foundation atau C_ARGV dan C_ARGC.

Pustaka standar Swift berisi struct CommandLineyang memiliki kumpulan Strings yang disebut arguments. Jadi Anda bisa mengaktifkan argumen seperti ini:

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

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

    default:
        print("an argument")
    }
}
Mark Adams
sumber
10
@AlbinStigo Process.arguments sudah berupa larik string, tidak perlu membuat yang baru.
Lance
9
Karena hampir selalu jawaban terbaik bukanlah yang diterima. :)
HepaKKes
5
Jika ada orang selain saya yang peduli, Proses sebenarnya adalah pencacahan .
robobrobro
1
Apakah Process.argumentssama dengan NSProcessInfo.processInfo().arguments?
Franklin Yu
5
Dalam snapshot Swift terbaru (baik snapshot 7/28 atau snapshot 7/29), Processobjek sekarang dikenal sebagai CommandLineobjek. Ini mungkin akan digabungkan sepenuhnya setelah Swift 3.0 secara resmi dirilis.
TheSoundDefense
57

Di Swift 3 gunakan CommandLineenum, bukanProcess

Begitu:

let arguments = CommandLine.arguments
Maciek Czarnik
sumber
46

Gunakan konstanta tingkat atas C_ARGCdan 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")
    }
}

Perhatikan bahwa saya menggunakan kisaran 1..C_ARGCkarena elemen pertama dari C_ARGV"array" adalah jalur aplikasi.

The C_ARGVvariabel tidak benar-benar sebuah array tetapi sub-skrip seperti array.

orj
sumber
4
Anda juga dapat menggunakan NSProcessInfo, seperti yang Anda lakukan di Objective-C.
Jack Lawrence
3
NSProcessInfo membutuhkan Foundation. Jawaban saya tidak membutuhkan Foundation. Hanya menggunakan lib standar lang swift.
orj
7
C_ARCGsepertinya tidak lagi didukung.
juandesant
2
Saya dapat mengonfirmasi bahwa C_ARG tidak lagi berfungsi dengan versi alat terbaru, XCode Versi 7.1 (7B91b).
svth
8
Sebagai gantinya Anda dapat menggunakan Process.argcdan Process.argumentsuntuk ini, meskipun sepertinya ini mungkin berubah menjadi CommandLine.argcdan CommandLine.argumentsdengan perubahan terbaru pada bahasa.
TheSoundDefense
14

Siapapun yang ingin menggunakan "getopt" lama (yang tersedia di Swift) dapat menggunakan ini sebagai referensi. Saya membuat port Swift dari contoh GNU di C yang dapat ditemukan di:

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

dengan deskripsi lengkap. Sudah teruji dan berfungsi penuh. Itu juga tidak membutuhkan 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)])!)'")
}
Michele Dall'Agata
sumber
0

Anda bisa membuat pengurai argumen dengan menggunakan CommandLine.arguments Array dan menambahkan logika apa pun yang Anda suka.

Anda bisa mengujinya. Buat 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)
}

kompilasi dan jalankan:

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

Masalah dengan Anda membangun parser argumen Anda sendiri adalah dengan mempertimbangkan semua konvensi argumen baris perintah. Saya akan merekomendasikan menggunakan Argument Parser yang sudah ada.

Anda bisa menggunakan:

  • Modul Konsol Vapor
  • TSCUtility Argument Parser digunakan oleh manajer Paket Swift
  • Swift Argument Parser bersumber terbuka oleh Apple

Saya telah menulis tentang bagaimana membangun alat baris perintah pada ketiganya. Anda harus memeriksanya dan memutuskan gaya apa yang paling cocok untuk Anda.

Jika Anda tertarik, berikut adalah tautannya:

Derik Ramirez
sumber