EDIT: Tolong, tolong , harap baca dua persyaratan yang tercantum di bagian bawah posting ini sebelum membalas. Orang-orang terus memposting permata dan perpustakaan baru mereka dan yang lainnya, yang jelas tidak memenuhi persyaratan.
Kadang-kadang saya ingin meretas beberapa opsi baris perintah dengan sangat murah menjadi skrip sederhana. Cara yang menyenangkan untuk melakukannya, tanpa berurusan dengan getopts atau parsing atau semacamnya, adalah:
...
$quiet = ARGV.delete('-d')
$interactive = ARGV.delete('-i')
...
# Deal with ARGV as usual here, maybe using ARGF or whatever.
Ini bukan sintaks opsi Unix yang normal, karena ini akan menerima opsi parameter baris perintah non-opsi, seperti dalam " myprog -i foo bar -q
", tetapi saya bisa menerimanya. (Beberapa orang, seperti para pengembang Subversion, lebih suka ini. Terkadang saya juga melakukannya.)
Opsi yang baru saja ada atau tidak ada tidak dapat diterapkan lebih sederhana dari yang di atas. (Satu tugas, satu panggilan fungsi, satu efek samping.) Apakah ada cara yang sama sederhananya untuk menangani opsi yang menggunakan parameter, seperti " -f
nama file "?
EDIT:
Satu hal yang tidak saya kemukakan sebelumnya, karena tidak menjadi jelas bagi saya sampai penulis Trollop menyebutkan bahwa perpustakaan tersebut sesuai "dalam satu file [800-baris]," adalah bahwa saya tidak hanya mencari yang bersih sintaks, tetapi untuk teknik yang memiliki karakteristik sebagai berikut:
Keseluruhan kode dapat dimasukkan ke dalam file skrip (tanpa membebani skrip itu sendiri, yang mungkin hanya beberapa lusin baris), sehingga seseorang dapat meletakkan satu file di
bin
direktori pada sistem apa pun dengan standar Ruby 1.8 . [5-7] instalasi dan menggunakannya. Jika Anda tidak dapat menulis skrip Ruby yang tidak memiliki pernyataan require dan kode untuk mengurai beberapa opsi berada di bawah selusin baris atau lebih, Anda gagal dalam persyaratan ini.Kode ini kecil dan cukup sederhana sehingga orang dapat cukup mengingatnya untuk langsung mengetik kode yang akan melakukan trik, daripada memotong dan menempel dari tempat lain. Pikirkan situasi di mana Anda berada di konsol server yang di-firewall tanpa akses Internet, dan Anda ingin menggabungkan skrip cepat untuk digunakan klien. Saya tidak tahu tentang Anda, tetapi (selain gagal memenuhi persyaratan di atas) menghafal bahkan 45 baris mikro-optparse yang disederhanakan bukanlah sesuatu yang ingin saya lakukan.
getoptlong
danoptparse
berada di pustaka ruby standar, jadi Anda TIDAK PERLU menyalinnya saat menerapkan skrip Anda - jika ruby berfungsi pada mesin itu, makarequire 'optparse'
ataurequire 'getoptlong'
akan berfungsi juga.Jawaban:
Sebagai penulis Trollop , saya tidak PERCAYA hal-hal yang menurut orang masuk akal dalam pengurai opsi. Sungguh. Itu mengejutkan pikiran.
Mengapa saya harus membuat modul yang memperluas beberapa modul lain ke opsi parse? Mengapa saya harus membuat subkelas apapun? Mengapa saya harus berlangganan beberapa "framework" hanya untuk mengurai baris perintah?
Berikut versi Trollop di atas:
Dan itu dia.
opts
sekarang menjadi hash dengan kunci:quiet
,:interactive
dan:filename
. Anda dapat melakukan apapun yang Anda inginkan dengannya. Dan Anda mendapatkan halaman bantuan yang indah, diformat agar sesuai dengan lebar layar Anda, nama argumen pendek otomatis, pemeriksaan jenis ... semua yang Anda butuhkan.Itu satu file, jadi Anda bisa meletakkannya di direktori lib / jika Anda tidak menginginkan ketergantungan formal. Ini memiliki DSL minimal yang mudah diambil.
LOC per orang pilihan. Itu penting.
sumber
Saya berbagi ketidaksukaan Anda
require 'getopts'
, terutama karena kedahsyatannya yaituOptionParser
:sumber
Berikut teknik standar yang biasa saya gunakan:
sumber
lib
folder atau kode Anda dan menggunakannya bahkan tanpa menyentuh rubygems.when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")
kewhen /^-/ then usage("Unknown option: #{ARGV.shift.inspect}")
atau itu akan menjadi loop penggunaan tak terbatasKarena tidak ada yang menyebutkannya, dan judulnya memang merujuk pada penguraian baris perintah yang murah , mengapa tidak membiarkan penerjemah Ruby yang mengerjakannya untuk Anda? Jika Anda melewatkan
-s
sakelar (di shebang Anda, misalnya), Anda mendapatkan sakelar sederhana secara gratis, yang ditetapkan ke variabel global huruf tunggal. Inilah contoh Anda menggunakan sakelar itu:Dan inilah hasilnya ketika saya menyimpannya sebagai
./test
dan chmod-nya+x
:Lihat
ruby -h
untuk detailnya.Itu pasti semurah yang didapat. Ini akan memunculkan NameError jika Anda mencoba sakelar seperti
-:
, jadi ada beberapa validasi di sana. Tentu saja, Anda tidak dapat memiliki sakelar setelah argumen non-sakelar, tetapi jika Anda membutuhkan sesuatu yang mewah, Anda benar-benar harus menggunakan OptionParser minimum. Faktanya, satu-satunya hal yang mengganggu saya tentang teknik ini adalah Anda akan mendapatkan peringatan (jika Anda mengaktifkannya) saat mengakses variabel global yang tidak disetel, tetapi masih salah, jadi ini berfungsi dengan baik untuk alat sekali pakai dan cepat. skrip.Satu peringatan yang ditunjukkan oleh FelipeC dalam komentar di " Bagaimana melakukan parsing opsi baris perintah yang sangat murah di Ruby ", adalah bahwa shell Anda mungkin tidak mendukung shebang 3-token; Anda mungkin perlu mengganti
/usr/bin/env ruby -w
dengan jalur sebenarnya ke ruby Anda (seperti/usr/local/bin/ruby -w
), atau menjalankannya dari skrip pembungkus, atau sesuatu.sumber
Saya membangun mikro-optparse untuk memenuhi kebutuhan yang jelas ini akan parser opsi yang singkat namun mudah digunakan. Ini memiliki sintaks yang mirip dengan Trollop dan pendek 70 baris. Jika Anda tidak memerlukan validasi dan dapat melakukannya tanpa baris kosong, Anda dapat memotongnya menjadi 45 baris. Saya pikir itulah yang Anda cari.
Contoh singkat:
Memanggil skrip dengan
-h
atau--help
akan dicetakIa memeriksa apakah input berjenis sama dengan nilai default, menghasilkan aksesor pendek dan panjang, mencetak pesan kesalahan deskriptif jika argumen tidak valid diberikan dan banyak lagi.
Saya membandingkan beberapa pengurai opsi dengan menggunakan setiap pengurai opsi untuk masalah yang saya miliki. Anda dapat menggunakan contoh ini dan ringkasan saya untuk membuat keputusan yang informatif. Jangan ragu untuk menambahkan lebih banyak implementasi ke daftar. :)
sumber
optparse
yang (memberi atau menerima) 1937 baris.optparse
merupakan library default, yaitu ia dikirimkan dengan setiap instalasi ruby.Trollop
adalah pustaka pihak ketiga, oleh karena itu Anda harus mengimpor kode lengkap setiap kali Anda ingin memasukkannya ke dalam proyek. µ-optparse selalu hanya membutuhkan ~ 70 baris, karenaoptparse
sudah ada.Saya sangat mengerti mengapa Anda ingin menghindari optparse - ini bisa menjadi terlalu banyak. Tetapi ada beberapa solusi yang jauh "lebih ringan" (dibandingkan dengan OptParse) yang datang sebagai pustaka tetapi cukup sederhana untuk membuat satu instalasi gem berharga.
Misalnya, lihat contoh OptiFlag ini . Hanya beberapa baris untuk diproses. Contoh yang sedikit terpotong yang disesuaikan dengan kasus Anda:
Ada banyak contoh yang disesuaikan juga . Saya ingat menggunakan yang lain yang lebih mudah, tetapi untuk saat ini telah luput dari saya tetapi saya akan kembali dan menambahkan komentar di sini jika saya menemukannya.
sumber
Inilah yang saya gunakan untuk argumen yang sangat, sangat murah:
jadi jika Anda menjalankannya
programname foo bar
panggilan foo dan kemudian bar. Ini berguna untuk skrip sekali pakai.sumber
Anda dapat mencoba sesuatu seperti:
sumber
Sudahkah Anda mempertimbangkan Thor dengan wycats? Saya pikir ini jauh lebih bersih daripada optparse. Jika Anda sudah memiliki skrip yang ditulis, mungkin perlu lebih banyak pekerjaan untuk memformatnya atau memfaktor ulangnya untuk thor, tetapi itu membuat opsi penanganan menjadi sangat sederhana.
Berikut cuplikan contoh dari README:
Thor secara otomatis memetakan perintah seperti:
Itu akan diubah menjadi:
sumber
--help
keluaran? Bagaimana jika "head myprogram.rb" adalah keluaran bantuan?Inilah pengurai opsi cepat-dan-kotor favorit saya:
Opsinya adalah ekspresi reguler, jadi "-h" juga akan cocok dengan "--help".
Dapat dibaca, mudah diingat, tidak ada perpustakaan eksternal, dan kode minimal.
sumber
/-h(\b|elp)
Trollop cukup murah.
sumber
Jika Anda menginginkan parser baris perintah sederhana untuk perintah kunci / nilai tanpa menggunakan permata:
Tetapi ini hanya berfungsi jika Anda selalu memiliki pasangan kunci / nilai.
Jika Anda tidak 'memerlukan pemeriksaan, Anda bisa menggunakan:
sumber
Berikut cuplikan kode yang saya gunakan di bagian atas sebagian besar skrip saya:
Saya juga tidak suka meminta file tambahan dalam skrip cepat-dan-kotor saya. Solusi saya hampir seperti yang Anda minta. Saya menempelkan potongan 10 baris kode di bagian atas salah satu skrip saya yang mengurai baris perintah dan menempelkan argumen posisi dan beralih ke objek Hash (biasanya ditugaskan ke objek yang saya beri nama arghash dalam contoh di bawah).
Berikut adalah contoh baris perintah yang mungkin ingin Anda parse ...
Yang akan menjadi Hash seperti ini.
Selain itu, dua metode kemudahan ditambahkan ke Hash:
argc()
akan mengembalikan jumlah argumen non-sakelar.switches()
akan mengembalikan array yang berisi kunci untuk sakelar yang adaIni berarti mengizinkan beberapa barang cepat dan kotor seperti ...
arghash.argc == 2
)arghash[1]
selalu mendapatkan argumen non-sakelar kedua).arghash['--max=']
yang menghasilkan nilai '15' dengan contoh baris perintah.arghash['-s']
yang mengevaluasi benar jika ada dan nol jika tidak ada.Uji keberadaan sakelar atau sakelar alternatif menggunakan operasi set seperti
puts USAGETEXT if !(%w(-h --help) & arghash.switches()).empty?
Identifikasi penggunaan sakelar yang tidak valid menggunakan operasi yang ditetapkan seperti
puts "Invalid switch found!" if !(arghash.switches - %w(-valid1 -valid2)).empty?
Tentukan nilai default untuk argumen yang hilang menggunakan yang sederhana
Hash.merge()
seperti contoh di bawah ini yang mengisi nilai untuk -max = jika tidak ada dan menambahkan argumen posisi ke-4 jika tidak diteruskan.with_defaults = {'-max=' => 20, 3 => 'default.txt'}.merge(arghash)
sumber
=
) dapat membuat perbedaan dalam kode yang Anda butuhkan.Ini sangat mirip dengan jawaban yang diterima, tetapi
ARGV.delete_if
yang saya gunakan adalah yang saya gunakan dalam parser sederhana saya . Satu-satunya perbedaan nyata adalah bahwa opsi dengan argumen harus bersama-sama (misalnya-l=file
).sumber
Rupanya @WilliamMorgan dan saya pikir sama. Saya baru saja merilis tadi malam ke Github yang sekarang saya lihat adalah perpustakaan yang mirip dengan Trollop (Dinamakan bagaimana?) Setelah melakukan pencarian untuk OptionParser di Github, lihat Switches
Ada beberapa perbedaan, tetapi filosofinya sama. Satu perbedaan yang jelas adalah bahwa Switch bergantung pada OptionParser.
sumber
Saya sedang mengembangkan permata pengurai opsi saya sendiri yang disebut Acclaim .
Saya menulisnya karena saya ingin membuat antarmuka baris perintah bergaya git dan dapat dengan rapi memisahkan fungsionalitas dari setiap perintah ke dalam kelas yang terpisah, tetapi juga dapat digunakan tanpa seluruh kerangka perintah:
Belum ada rilis stabil, tetapi saya sudah menerapkan beberapa fitur seperti:
Ada banyak penekanan pada perintah sehingga mungkin agak berat untuk penguraian baris perintah sederhana tetapi berfungsi dengan baik dan saya telah menggunakannya di semua proyek saya. Jika Anda tertarik dengan aspek antarmuka perintah, lihat halaman GitHub proyek untuk informasi dan contoh lebih lanjut.
sumber
Misalkan sebuah perintah memiliki paling banyak satu tindakan dan jumlah opsi yang berubah-ubah seperti ini:
Penguraian tanpa validasi mungkin seperti ini:
sumber
https://github.com/soveran/clap
46LOC (pada 1.0.0), tidak ada ketergantungan pada pengurai opsi eksternal. Menyelesaikan pekerjaan. Mungkin tidak berfitur lengkap seperti yang lain, tapi 46LOC.
Jika Anda memeriksa kode, Anda dapat dengan mudah menduplikasi teknik yang mendasarinya - tetapkan lambda dan gunakan arity untuk memastikan jumlah argumen yang tepat mengikuti bendera jika Anda benar-benar tidak menginginkan perpustakaan eksternal.
Sederhana. Murah.
EDIT : konsep yang mendasari diringkas karena saya kira Anda dapat menyalin / menempelkannya ke dalam skrip untuk membuat parser baris perintah yang masuk akal. Ini jelas bukan sesuatu yang ingin saya hafalkan, tetapi menggunakan lambda arity sebagai pengurai murah adalah ide baru:
sumber
Saya akan membagikan pengurai opsi sederhana saya sendiri yang telah saya kerjakan selama beberapa waktu. Ini hanyalah 74 baris kode, dan melakukan dasar-dasar dari apa yang dilakukan pengurai opsi internal Git. Saya mengambil OptionParser sebagai inspirasi, dan juga Git's.
https://gist.github.com/felipec/6772110
Ini terlihat seperti ini:
sumber
EasyOptions sama sekali tidak memerlukan kode penguraian opsi. Cukup tulis teks bantuan, minta, selesai.
sumber