Untuk sebagian besar kasus, Anda tidak memerlukan parser eksternal. Pencocokan pola Scala memungkinkan penggunaan args dalam gaya fungsional. Sebagai contoh:
object MmlAlnApp {
val usage = """
Usage: mmlaln [--min-size num] [--max-size num] filename
"""
def main(args: Array[String]) {
if (args.length == 0) println(usage)
val arglist = args.toList
type OptionMap = Map[Symbol, Any]
def nextOption(map : OptionMap, list: List[String]) : OptionMap = {
def isSwitch(s : String) = (s(0) == '-')
list match {
case Nil => map
case "--max-size" :: value :: tail =>
nextOption(map ++ Map('maxsize -> value.toInt), tail)
case "--min-size" :: value :: tail =>
nextOption(map ++ Map('minsize -> value.toInt), tail)
case string :: opt2 :: tail if isSwitch(opt2) =>
nextOption(map ++ Map('infile -> string), list.tail)
case string :: Nil => nextOption(map ++ Map('infile -> string), list.tail)
case option :: tail => println("Unknown option "+option)
exit(1)
}
}
val options = nextOption(Map(),arglist)
println(options)
}
}
akan dicetak, misalnya:
Map('infile -> test/data/paml-aln1.phy, 'maxsize -> 4, 'minsize -> 2)
Versi ini hanya membutuhkan satu infile. Mudah ditingkatkan (dengan menggunakan Daftar).
Perhatikan juga bahwa pendekatan ini memungkinkan untuk menggabungkan beberapa argumen baris perintah - bahkan lebih dari dua!
nextOption
bukan nama yang baik untuk fungsi ini. Ini adalah fungsi yang mengembalikan peta - fakta bahwa itu adalah rekursif adalah detail implementasi. Ini seperti menulismax
fungsi untuk koleksi dan menyebutnyanextMax
hanya karena Anda menulisnya dengan rekursi eksplisit. Kenapa tidak menyebutnya sajaoptionMap
?listToOptionMap(lst:List[String])
dengan fungsi yangnextOption
didefinisikan di dalamnya, dengan pepatah baris terakhirreturn nextOption(Map(), lst)
. Yang mengatakan, saya harus mengakui bahwa saya telah membuat lebih banyak jalan pintas mengerikan dalam waktu saya daripada yang ada di jawaban ini.exit(1)
mungkin perlusys.exit(1)
file
parameter:case string :: tail => { if (isSwitch(string)) { println("Unknown option: " + string) sys.exit(1) } else nextOption(map ++ Map('files -> (string :: map('files).asInstanceOf[List[String]])), tail)
. Peta juga membutuhkan nilai defaultNil
, yaituval options = nextOption(Map() withDefaultValue Nil, args.toList)
. Apa yang saya tidak suka adalah harus menggunakanasInstanceOf
, karenaOptionMap
nilai - nilai yang bertipeAny
. Apakah ada solusi yang lebih baik?scopt / scopt
Di atas menghasilkan teks penggunaan berikut:
Inilah yang saat ini saya gunakan. Bersihkan penggunaan tanpa terlalu banyak bagasi. (Penafian: Saya sekarang mengelola proyek ini)
sumber
Saya menyadari bahwa pertanyaan itu diajukan beberapa waktu yang lalu, tetapi saya pikir itu mungkin membantu beberapa orang, yang mencari-cari di sekitar (seperti saya), dan membuka halaman ini.
Scallop terlihat cukup menjanjikan juga.
Fitur (kutipan dari halaman github tertaut):
Dan beberapa kode contoh (juga dari halaman Github itu):
sumber
(x, c) => c.copy(xyz = x)
di pilihSaya suka menggeser argumen untuk konfigurasi yang relatif sederhana.
sumber
args.sliding(2, 2)
?var port = 0
?Toolkit Scala Antarmuka Baris Perintah (CLIST)
ini milikku juga! (meskipun agak terlambat dalam permainan)
https://github.com/backuity/clist
Berbeda dengan
scopt
itu sepenuhnya bisa berubah ... tapi tunggu! Itu memberi kita sintaks yang cukup bagus:Dan cara sederhana untuk menjalankannya:
Anda dapat melakukan lebih banyak tentu saja (multi-perintah, banyak opsi konfigurasi, ...) dan tidak memiliki ketergantungan.
Saya akan selesai dengan semacam fitur khas, penggunaan default (cukup sering diabaikan untuk banyak perintah):
sumber
Password
,Hex
, ...), maka Anda dapat memanfaatkan ini.Ini sebagian besar merupakan tiruan tak tahu malu dari jawaban saya untuk pertanyaan Java tentang topik yang sama . Ternyata JewelCLI ramah-Scala karena tidak memerlukan metode gaya JavaBean untuk mendapatkan penamaan argumen otomatis.
JewelCLI adalah perpustakaan Java Scala-friendly untuk parsing baris perintah yang menghasilkan kode bersih . Menggunakan Proxied Interfaces Configured with Annotations untuk secara dinamis membangun API tipe-aman untuk parameter baris perintah Anda.
Contoh antarmuka parameter
Person.scala
:Contoh penggunaan antarmuka parameter
Hello.scala
:Simpan salinan file-file di atas ke satu direktori dan unduh JewelCLI 0,6 JAR ke direktori itu juga.
Kompilasi dan jalankan contoh di Bash di Linux / Mac OS X / etc .:
Kompilasi dan jalankan contoh di Prompt Perintah Windows:
Menjalankan contoh harus menghasilkan output berikut:
sumber
Cara mengurai parameter tanpa ketergantungan eksternal. Pertanyaan bagus! Anda mungkin tertarik pada picocli .
Picocli dirancang khusus untuk menyelesaikan masalah yang diajukan dalam pertanyaan: itu adalah kerangka penguraian baris perintah dalam satu file, sehingga Anda dapat memasukkannya dalam bentuk sumber . Ini memungkinkan pengguna menjalankan aplikasi berbasis picocli tanpa memerlukan picocli sebagai ketergantungan eksternal .
Ini bekerja dengan bidang anotasi sehingga Anda menulis kode yang sangat sedikit. Ringkasan cepat:
<command> -xvfInputFile
serta<command> -x -v -f InputFile
)"1..*"
,"3..5"
Pesan bantuan penggunaan mudah disesuaikan dengan anotasi (tanpa pemrograman). Sebagai contoh:
( sumber )
Saya tidak bisa menolak menambahkan satu tangkapan layar lagi untuk menunjukkan pesan bantuan penggunaan seperti apa yang mungkin. Bantuan penggunaan adalah wajah aplikasi Anda, jadi jadilah kreatif dan bersenang-senang!
Penafian: Saya membuat picocli. Umpan balik atau pertanyaan sangat disambut. Itu ditulis dalam java, tetapi beri tahu saya jika ada masalah menggunakannya dalam scala dan saya akan mencoba mengatasinya.
sumber
Saya dari dunia Java, saya suka args4j karena sederhana, spesifikasinya lebih mudah dibaca (terima kasih pada anotasi) dan menghasilkan keluaran yang diformat dengan baik.
Berikut ini cuplikan contoh saya:
Spesifikasi
Parse
Pada argumen yang tidak valid
sumber
scala-optparse-aplikatif
Saya pikir scala-optparse-aplikatif adalah parser baris perintah perpustakaan paling fungsional di Scala.
https://github.com/bmjames/scala-optparse-applicative
sumber
examples
di kode tesAda juga JCommander (penafian: Saya membuatnya):
sumber
Saya menyukai pendekatan slide () dari joslinm, bukan vars yang bisa berubah;) Jadi, inilah cara yang tidak dapat diubah untuk pendekatan itu:
sumber
Saya baru saja menemukan perpustakaan parsing baris perintah yang luas dalam paket scala.tools.cmd scalac.
Lihat http://www.assembla.com/code/scala-eclipse-toolchain/git/nodes/src/compiler/scala/tools/cmd?rev=f59940622e32384b1e08939effd24e924a8ba8db
sumber
Saya telah mencoba menggeneralisasi solusi @ pjotrp dengan memasukkan daftar simbol kunci posisi yang diperlukan, peta bendera -> simbol kunci dan opsi default:
sumber
-f|--flags
. Lihatlah gist.github.com/DavidGamba/b3287d40b019e498982c dan jangan ragu untuk memperbarui jawabannya jika Anda menyukainya. Saya mungkin akan membuat setiap Peta dan opsi sehingga Anda hanya bisa memberikan apa yang Anda perlukan dengan argumen bernama.Saya mendasarkan pendekatan saya pada jawaban teratas (dari dave4420), dan mencoba memperbaikinya dengan menjadikannya lebih umum.
Ini mengembalikan a
Map[String,String]
dari semua parameter baris perintah Anda dapat menanyakan ini untuk parameter spesifik yang Anda inginkan (misalnya menggunakan.contains
) atau mengubah nilai menjadi tipe yang Anda inginkan (misalnya menggunakantoInt
).Contoh:
Memberi:
sumber
perpustakaan lain: scarg
sumber
Berikut adalah pengurai baris perintah scala yang mudah digunakan. Secara otomatis memformat teks bantuan, dan itu mengonversi argumen beralih ke jenis yang Anda inginkan. Baik POSIX pendek, dan sakelar gaya GNU panjang didukung. Mendukung sakelar dengan argumen yang diperlukan, argumen opsional, dan argumen multi nilai. Anda bahkan dapat menentukan daftar nilai terbatas yang dapat diterima untuk sakelar tertentu. Nama saklar panjang dapat disingkat pada baris perintah untuk kenyamanan. Mirip dengan parser opsi di pustaka standar Ruby.
sumber
Saya tidak pernah suka ruby like parser opsi. Sebagian besar pengembang yang menggunakannya tidak pernah menulis halaman manual yang tepat untuk skrip mereka dan berakhir dengan pilihan halaman panjang tidak terorganisir dengan cara yang tepat karena parser mereka.
Saya selalu lebih suka cara Perl melakukan sesuatu dengan Perl's Getopt :: Long .
Saya sedang mengerjakan implementasi scala itu. API awal terlihat seperti ini:
Jadi panggilan
script
seperti ini:Akan mencetak:
Dan kembali:
Proyek ini diselenggarakan di github scala-getoptions .
sumber
Saya baru saja membuat enumerasi sederhana saya
Saya mengerti bahwa solusi memiliki dua kelemahan utama yang dapat mengalihkan perhatian Anda: Solusi ini menghilangkan kebebasan (yaitu ketergantungan pada perpustakaan lain, yang sangat Anda hargai) dan redundansi (prinsip KERING, Anda mengetikkan nama opsi hanya satu kali, seperti program Scala variabel dan menghilangkannya kedua kalinya diketik sebagai teks baris perintah).
sumber
Saya sarankan untuk menggunakan http://docopt.org/ . Ada scala-port tetapi implementasi Java https://github.com/docopt/docopt.java berfungsi dengan baik dan tampaknya lebih baik dipertahankan. Ini sebuah contoh:
sumber
Ini yang saya masak. Ini mengembalikan tuple peta dan daftar. Daftar adalah untuk input, seperti nama file input. Peta untuk sakelar / opsi.
akan kembali
Switch dapat berupa "--t" yang x akan disetel ke true, atau "--x 10" yang x akan diatur ke "10". Segala sesuatu yang lain akan berakhir dalam daftar.
sumber
Saya suka tampilan bersih dari kode ini ... diperoleh dari diskusi di sini: http://www.scala-lang.org/old/node/4380
sumber
Karena semua orang memposting solusi sendiri di sini adalah milik saya, karena saya ingin sesuatu yang lebih mudah untuk ditulis untuk pengguna: https://gist.github.com/gwenzek/78355526e476e08bb34d
Intinya berisi file kode, ditambah file uji dan contoh singkat yang disalin di sini:
Tidak ada opsi mewah untuk memaksa variabel berada dalam beberapa batasan, karena saya tidak merasa bahwa parser adalah tempat terbaik untuk melakukannya.
Catatan: Anda dapat memiliki alias sebanyak yang Anda inginkan untuk variabel yang diberikan.
sumber
Saya akan menumpuk. Saya memecahkan ini dengan garis kode sederhana. Argumen baris perintah saya terlihat seperti ini:
Ini menciptakan sebuah array melalui fungsi baris perintah asli Scala (dari salah satu Aplikasi atau metode utama):
Saya kemudian dapat menggunakan baris ini untuk mem-parsing array default args:
Yang membuat peta dengan nama yang terkait dengan nilai-nilai baris perintah:
Saya kemudian dapat mengakses nilai-nilai parameter bernama dalam kode saya dan urutan mereka muncul di baris perintah tidak lagi relevan. Saya menyadari ini cukup sederhana dan tidak memiliki semua fungsi canggih yang disebutkan di atas tetapi tampaknya cukup dalam banyak kasus, hanya membutuhkan satu baris kode, dan tidak melibatkan dependensi eksternal.
sumber
Ini milikku 1-liner
Itu menjatuhkan 3 argumen wajib dan memberikan opsi. Integer ditentukan seperti
-Xmx<size>
opsi java terkenal , bersama dengan awalan. Anda dapat mengurai binari dan bilangan bulat sesederhanaTidak perlu mengimpor apa pun.
sumber
One-liner cepat dan kotor orang miskin untuk kunci parsing = pasangan nilai:
sumber
freecli
Ini akan menghasilkan penggunaan berikut:
Pemakaian
sumber