রুবিতে সত্যই সস্তা কমান্ড-লাইন বিকল্প পার্সিং


114

সম্পাদনা: দয়া করে , দয়া করে , উত্তর দেওয়ার আগে এই পোস্টের নীচে তালিকাভুক্ত দুটি প্রয়োজনীয়তা পড়ুন। লোকেরা তাদের নতুন রত্ন এবং গ্রন্থাগারগুলি পোস্ট করে রাখে এবং কী নয়, যা স্পষ্টভাবে প্রয়োজনীয়তাগুলি পূরণ করে না।

কখনও কখনও আমি খুব সস্তায় একটি সাধারণ স্ক্রিপ্টে কিছু কমান্ড লাইন বিকল্প হ্যাক করতে চাই। গিওপটস বা পার্সিং বা এ জাতীয় কিছু না করেই এটি করার একটি মজাদার উপায়:

...
$quiet       = ARGV.delete('-d')
$interactive = ARGV.delete('-i')
...
# Deal with ARGV as usual here, maybe using ARGF or whatever.

এটি একেবারে সাধারণ ইউনিক্স বিকল্পের বাক্য গঠন নয়, কারণ এটি বিকল্প হিসাবে নন-অপশন কমান্ড লাইন প্যারামিটারগুলি গ্রহণ করবে, " myprog -i foo bar -q" তবে আমি তার সাথে বাঁচতে পারি। (কিছু লোক, যেমন সাবভার্সন বিকাশকারীরা এটিকে পছন্দ করে Sometimes কখনও কখনও আমিও এটি করি))

উপরের তুলনায় কেবলমাত্র উপস্থিত বা অনুপস্থিত একটি বিকল্প প্রয়োগ করা যায় না। (একটি অ্যাসাইনমেন্ট, একটি ফাংশন কল, এক পার্শ্ব প্রতিক্রিয়া)) " -f ফাইলের নাম " এর মতো পরামিতি গ্রহণকারী বিকল্পগুলির সাথে মোকাবিলা করার জন্য কি একইরকম সহজ উপায় আছে ?

সম্পাদনা করুন:

একটি বিষয় আমি এর আগে তৈরি করিনি, কারণ ট্রোলপের লেখক উল্লেখ না করা পর্যন্ত এটি আমার কাছে স্পষ্ট হয়ে ওঠে নি যে লাইব্রেরিটি "একটি [800-লাইন] ফাইলে" ফিট করে, আমি কেবল পরিষ্কারের জন্যই দেখছি না বাক্য গঠন, তবে এমন একটি প্রযুক্তির জন্য যা নিম্নলিখিত বৈশিষ্ট্যগুলি রয়েছে:

  1. কোডটির সম্পূর্ণতা স্ক্রিপ্ট ফাইলটিতে অন্তর্ভুক্ত করা যেতে পারে (আসল স্ক্রিপ্টটি নিজেরাই না ছাপিয়ে, যা কেবলমাত্র কয়েক ডজন লাইন হতে পারে), যাতে binকোনও স্ট্যান্ডার্ড রুবি ১.৮ সহ যে কোনও সিস্টেমে একটি ফাইল একটি ডিয়ারে ফেলে দিতে পারে one । [5-7] ইনস্টলেশন এবং এটি ব্যবহার করুন। আপনি যদি কোনও রুবি স্ক্রিপ্ট লিখতে না পারেন যার কোনও বিবৃতি নেই এবং যেখানে কয়েকটি বিকল্পের বিশ্লেষণের কোডটি কয়েক ডজন লাইনের অধীনে রয়েছে, আপনি এই প্রয়োজনীয়তাটি ব্যর্থ হন।

  2. কোডটি ছোট এবং যথেষ্ট সহজ যে কোনওটি সরাসরি কোড টাইপ করার জন্য এটির যথেষ্ট পরিমাণে মনে রাখতে পারে যা অন্য কোথাও থেকে কাটা এবং পেস্ট করার চেয়ে কৌশলটি করবে। আপনি যেখানে কোনও ইন্টারনেট অ্যাক্সেসবিহীন ফায়ারওয়াল্ড সেভারের কনসোলে রয়েছেন সেই পরিস্থিতিটি ভেবে দেখুন এবং ক্লায়েন্টকে ব্যবহারের জন্য আপনি একটি দ্রুত স্ক্রিপ্ট টস করতে চান। আমি আপনার সম্পর্কে জানি না, তবে (উপরের প্রয়োজনে ব্যর্থ হওয়া ছাড়াও) সরলিকৃত মাইক্রো অপ্ট পার্সির 45 টি লাইন মুখস্থ করা আমার করণীয় নয়।


2
গেটোপলংয়ের বিরুদ্ধে আপত্তি নিয়ে কি কৌতূহল?
মার্ক কেরি

এটির ভার্বোসটি। গিওপট্লগের সাহায্যে, কখনও কখনও বিকল্পগুলি পার্সিং কোডটি স্ক্রিপ্টের অংশটির চেয়ে দীর্ঘ হয় যা আসলে কাজ করে। এটি কেবল একটি নান্দনিক সমস্যা নয়, তবে রক্ষণাবেক্ষণ ব্যয়ের সমস্যা।
সিজেএস

8
আমি স্ক্রিপ্ট অন্তর্ভুক্তির প্রয়োজনীয়তা বুঝতে পারি না - উভয়ই getoptlongএবং optparseমানক রুবি লাইব্রেরিতে থাকি , সুতরাং আপনার স্ক্রিপ্টটি মোতায়েন করার সময় আপনি সেগুলি অনুলিপি করার প্রয়োজন নেই - যদি রুবি সেই মেশিনে কাজ করে, require 'optparse'বা require 'getoptlong'খুব কাজ করবে।
রায়পুম

দেখুন stackoverflow.com/questions/21357953/... , সেইসাথে যত্নহীন সম্পর্কে নিচে উইলিয়াম মর্গান এর উত্তর।
নির্ভীক_ফুল

@ কার্টস্যাম্পসন আমি বিশ্বাস করতে পারি না কত জন আপনার প্রশ্নের উত্তর দেয়নি। যেভাবেই হোক, অবশেষে 3 টি পোস্ট সম্পর্কে একটি ভাল উত্তর পেয়েছে এক্সডি এক্সডি
ওয়ানচিলডুড

উত্তর:


235

ট্রলোপের লেখক হিসাবে , আমি বিকল্পগুলির বিশ্লেষণকারীদের পার্সারে যে জিনিস যুক্তিসঙ্গত বলে মনে করি সেই জিনিসগুলিকে আমি বিশ্বাস করতে পারি না। সিরিয়াসলি। এটি মনকে ছটফট করে।

কেন আমাকে এমন একটি মডিউল তৈরি করতে হবে যা কিছু অন্যান্য মডিউলকে বিকল্পগুলি বিশ্লেষণ করতে প্রসারিত করে? আমার কেন কিছু উপক্লাস করা উচিত? কমান্ড লাইনটি বিশ্লেষণের জন্য কেন আমাকে কিছু "ফ্রেমওয়ার্ক" এ সাবস্ক্রাইব করতে হবে?

এখানে উপরের ট্রোল্প সংস্করণটি দেওয়া হয়েছে:

opts = Trollop::options do
  opt :quiet, "Use minimal output", :short => 'q'
  opt :interactive, "Be interactive"
  opt :filename, "File to process", :type => String
end

এবং এটাই. optsএখন কী এর মাধ্যমে একটি হ্যাশ হয় :quiet, :interactiveএবং :filename। আপনি এটি দিয়ে যা করতে পারেন তা করতে পারেন। এবং আপনি আপনার পর্দার প্রস্থ, স্বয়ংক্রিয় সংক্ষিপ্ত যুক্তি নাম, টাইপ চেকিং ... আপনার প্রয়োজনীয় সমস্ত ফিট করার জন্য ফর্ম্যাট করা একটি সুন্দর সহায়তা পৃষ্ঠা পান।

এটি একটি ফাইল, যাতে আপনি আনুষ্ঠানিক নির্ভরতা না চাইলে আপনি এটিকে আপনার lib / ডিরেক্টরিতে ফেলে দিতে পারেন। এটিতে একটি ন্যূনতম ডিএসএল রয়েছে যা তোলা সহজ।

এলওসি প্রতি বিকল্প লোক। এটা গুরুত্বপূর্ণ।


39
বিটিডাব্লু, ট্রোলপ লেখার জন্য +1 (যা ইতিমধ্যে এখানে উল্লেখ করা হয়েছিল) তবে প্রথম অনুচ্ছেদে কিছুটা নিচে নির্দ্বিধায় কথা বলতে পারেন।
সিজেএস

33
এই ক্ষেত্রে তার অভিযোগ করার অধিকার আছে আমি ভীত। আপনি যখন বিকল্পগুলি দেখুন: [1 ] [2 ] [3 ], মূলত কেবল একটি সরল স্ট্রিং অ্যারে প্রক্রিয়াজাতকরণের জন্য (আসলেই এটি ডুবে যাবেন না), আপনি সাহায্য করতে পারেন না কেন অবাক? আপনি এই সমস্ত ফোটা থেকে কি লাভ? এটি সি নয়, যেখানে স্ট্রিংগুলি "সমস্যাযুক্ত"। অবশ্যই প্রতিটি তার নিজস্ব। :)
srcspider

50
দয়া করে এটিকে কিছুটা বলবেন না। এটা একটা ধার্মিক দল, ভাই।
উইলিয়াম পিত্রি

7
দশম শব্দটি কিছুটা স্বরে নিচু করে দেখুন।
অ্যান্ড্রু গ্রিম

3
ট্রোলপের জন্য +1। আমি এটি আমার পরীক্ষার অটোমেশন সিস্টেমের জন্য ব্যবহার করি এবং এটি জাস্ট ওয়ার্ক করে। প্লাস এটির সাথে কোড করা এত সহজ যে আমি কখনও কখনও আমার ব্যানারটিকে এটির আনন্দ উপভোগ করার জন্য পুনরায় সাজাই।
কিনফ্রস্ট

76

আমি আপনার বিরক্তি ভাগ করছি require 'getopts', মূলত যে দুর্দান্ততার কারণে OptionParser:

% cat temp.rb                                                            
require 'optparse'
OptionParser.new do |o|
  o.on('-d') { |b| $quiet = b }
  o.on('-i') { |b| $interactive = b }
  o.on('-f FILENAME') { |filename| $filename = filename }
  o.on('-h') { puts o; exit }
  o.parse!
end
p :quiet => $quiet, :interactive => $interactive, :filename => $filename
% ruby temp.rb                                                           
{:interactive=>nil, :filename=>nil, :quiet=>nil}
% ruby temp.rb -h                                                        
Usage: temp [options]
    -d
    -i
    -f FILENAME
    -h
% ruby temp.rb -d                                                        
{:interactive=>nil, :filename=>nil, :quiet=>true}
% ruby temp.rb -i                                                        
{:interactive=>true, :filename=>nil, :quiet=>nil}
% ruby temp.rb -di                                                       
{:interactive=>true, :filename=>nil, :quiet=>true}
% ruby temp.rb -dif apelad                                               
{:interactive=>true, :filename=>"apelad", :quiet=>true}
% ruby temp.rb -f apelad -i                                              
{:interactive=>true, :filename=>"apelad", :quiet=>nil}

6
ধন্যবাদ, আমি দেখতে পাচ্ছি না যে এটি ওপিগুলির অনুরোধের সাথে কীভাবে খাপ খায় না, বিশেষত কোনও মানক কোড ইনস্টল / বিক্রেতার প্রয়োজনের তুলনায় এটি আদর্শভাবে
বিবেচনাধীন হিসাবে বিবেচনা করে

3
এটি অতিরিক্ত ট্রলের প্রয়োজন না বাদে ঠিক ট্রলাপ সংস্করণটির মতো দেখায়।
ক্লাদিউ

59

আমি সাধারণত যে স্ট্যান্ডার্ড কৌশলটি ব্যবহার করি তা এখানে:

#!/usr/bin/env ruby

def usage(s)
    $stderr.puts(s)
    $stderr.puts("Usage: #{File.basename($0)}: [-l <logfile] [-q] file ...")
    exit(2)
end

$quiet   = false
$logfile = nil

loop { case ARGV[0]
    when '-q' then  ARGV.shift; $quiet = true
    when '-l' then  ARGV.shift; $logfile = ARGV.shift
    when /^-/ then  usage("Unknown option: #{ARGV[0].inspect}")
    else break
end; }

# Program carries on here.
puts("quiet: #{$quiet} logfile: #{$logfile.inspect} args: #{ARGV.inspect}")

3
প্রশ্নের উত্তর, কিন্তু মানুষ, ট্রোলাপ মনে হয় এটি মোকাবেলা করা অনেক সহজ। প্রিমেড হুইলটি এত মসৃণ হলে চাকাটি পুনরায় উদ্ভাবন করা কেন?
মিকি টি কে

7
প্রিমেড হুইল মসৃণ নয়। প্রয়োজনীয়তার প্রতি যত্নবান হয়ে প্রশ্নটি আবার মনোযোগ সহকারে পড়ুন।
সিজেএস

2
+1 কখনও কখনও আপনার চাকাটি পুনরায় উদ্ভাবন করা প্রয়োজন, কারণ আপনি চান না বা কেবল ট্রললপের মতো অন্যান্য নির্ভরতা ব্যবহার করতে পারবেন না
lzap

রত্ন হিসাবে ট্রোলপ ইনস্টল করার দরকার নেই। আপনি কেবল একটি ফাইল এটি আপনার libফোল্ডার বা কোডে ফেলে দিতে পারেন এবং রুবিজেমস স্পর্শ না করেও এটি ব্যবহার করতে পারেন।
ওভারব্রাইড

আমার জন্য, আমাকে পরিবর্তন when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")করতে হয়েছিল when /^-/ then usage("Unknown option: #{ARGV.shift.inspect}")বা এটি অসীম ব্যবহারের লুপে উঠতে পারে
কেসি

36

যেহেতু কেউ এটা উল্লেখ করতে দেখা এবং শিরোনাম নেই পড়ুন সস্তা কম্যান্ড-লাইন পার্সিং না কেন শুধু Ruby ইন্টারপ্রেটারের আপনার জন্য কাজ করতে দেওয়া? আপনি যদি -sসুইচটি পাস করেন (উদাহরণস্বরূপ আপনার শেবাঙে), আপনি একক-বর্ণের গ্লোবাল ভেরিয়েবলগুলিতে নির্ধারিত, বিনামূল্যে ময়লা-সহজ স্যুইচগুলি পান। এই সুইচটি ব্যবহার করে আপনার উদাহরণটি এখানে:

#!/usr/bin/env ruby -s
puts "#$0: Quiet=#$q Interactive=#$i, ARGV=#{ARGV.inspect}"

এবং আউটপুট এখানে যখন আমি সেভ করব ./testএবং এটি chmod করব +x:

$ ./test
./test: Quiet= Interactive=, ARGV=[]
$ ./test -q foo
./test: Quiet=true Interactive=, ARGV=["foo"]
$ ./test -q -i foo bar baz
./test: Quiet=true Interactive=true, ARGV=["foo", "bar", "baz"]
$ ./test -q=very foo
./test: Quiet=very Interactive=, ARGV=["foo"]

দেখুন ruby -hবিস্তারিত জানার জন্য।

এটি অবশ্যই এটি হিসাবে সস্তার হতে হবে। আপনি যদি এমন একটি স্যুইচ চেষ্টা করেন তবে এটি একটি নেমরর উত্থাপন করবে -:, তাই কিছুটা বৈধতা আছে। অবশ্যই, একটি নন-স্যুইচ আর্গুমেন্টের পরে আপনার কোনও স্যুইচ থাকতে পারে না, তবে আপনার যদি অভিনব কিছু দরকার হয় তবে আপনার অবশ্যই সর্বনিম্ন অপশনপার্সার ব্যবহার করা উচিত। প্রকৃতপক্ষে, এই কৌশলটি সম্পর্কে আমাকে বিরক্ত করার একমাত্র জিনিসটি হ'ল কোনও আনসেট গ্লোবাল ভেরিয়েবল অ্যাক্সেস করার সময় আপনি একটি সতর্কতা পাবেন (যদি আপনি সেগুলি সক্ষম করে থাকেন) তবে এটি মিথ্যা, সুতরাং এটি নিক্ষিপ্ত সরঞ্জাম এবং দ্রুতর জন্য ঠিক কাজ করে স্ক্রিপ্ট।

"রুবিতে কীভাবে সত্যিকারের সস্তার কমান্ড-লাইন বিকল্প পার্সিং করা যায় " -র মন্তব্যে ফিলিপিসি দ্বারা নির্দেশিত একটি সতর্কতা হ'ল আপনার শেলটি সম্ভবত 3-টোকেন শেবাং সমর্থন করবে না; /usr/bin/env ruby -wআপনার রুবিতে আসল পথটি পরিবর্তন করতে (যেমন /usr/local/bin/ruby -w) দরকার হতে পারে , বা এটি একটি মোড়ক স্ক্রিপ্ট, বা অন্য কোনও কিছু থেকে চালানো যেতে পারে।


2
ধন্যবাদ :) আমি নিশ্চিত আশা করি তিনি গত দু'বছর ধরে এই উত্তরটির অপেক্ষায় ছিলেন না।
ডার্কহার্ট

3
আমি সত্যিই গত দুই বছর ধরে এই উত্তরটির জন্য অপেক্ষা করছিলাম। :-) আরও গুরুত্ব সহকারে, এটি আমি যা খুঁজছিলাম সেই চালাক চিন্তার ধরণ। সতর্কবার্তাটি কিছুটা বিরক্তিকর, তবে আমি এটি হ্রাস করার উপায়গুলি সম্পর্কে ভাবতে পারি।
সিজেএস

আমি খুশি (শেষ পর্যন্ত) সাহায্য করতে পারলাম, @ কর্টস্যাম্পসন, এমআরআই এর পতাকাগুলি সরাসরি পার্লের বাইরে ছিঁড়ে গেছে, যেখানে তারা শেল ওয়ান-লাইনারগুলিতে অকৃত্রিমভাবে ব্যবহার করার ঝোঁক রয়েছে। যদি উত্তরটি এখনও আপনার পক্ষে কার্যকর হয় তবে তা নির্দ্বিধায় গ্রহণ করুন। :)
বিজেবিবি

1
আপনি লিনাক্সের শেবাংয়ে একাধিক যুক্তি ব্যবহার করতে পারবেন না। / usr / bin / env: 'রুবি-এস': এ জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই
ফিলিপিসি

13

আমি সংক্ষিপ্ত, তবে সহজেই অপশন-পার্সার ব্যবহারের পক্ষে এই সুস্পষ্ট প্রয়োজনটি পূরণ করতে মাইক্রো অপট পার্সি তৈরি করেছি । এটি ট্রোলপের অনুরূপ একটি সিনট্যাক্স এবং 70 লাইন সংক্ষিপ্ত। যদি আপনার বৈধতাগুলির প্রয়োজন হয় না এবং খালি লাইনগুলি না করে আপনি এটি 45 টি লাইনে কেটে ফেলতে পারেন। আমি মনে করি আপনি ঠিক এটিই খুঁজছিলেন।

সংক্ষিপ্ত উদাহরণ:

options = Parser.new do |p|
  p.version = "fancy script version 1.0"
  p.option :verbose, "turn on verbose mode"
  p.option :number_of_chairs, "defines how many chairs are in the classroom", :default => 1
  p.option :room_number, "select room number", :default => 2, :value_in_set => [1,2,3,4]
end.process!

সাথে স্ক্রিপ্ট কল করছি -h বা --helpমুদ্রণ করবে

Usage: micro-optparse-example [options]
    -v, --[no-]verbose               turn on verbose mode
    -n, --number-of-chairs 1         defines how many chairs are in the classroom
    -r, --room-number 2              select room number
    -h, --help                       Show this message
    -V, --version                    Print version

এটি ইনপুট ডিফল্ট মান হিসাবে একই ধরণের কিনা তা পরীক্ষা করে, সংক্ষিপ্ত এবং দীর্ঘ অ্যাকসেসর উত্পন্ন করে, অবৈধ যুক্তি দেওয়া থাকলে এবং আরও অনেক কিছু বর্ণনামূলক ত্রুটি বার্তা প্রিন্ট করে।

আমি যে সমস্যাটি করেছি তার জন্য প্রতিটি অপশন-পার্সার ব্যবহার করে আমি বেশ কয়েকটি অপশন-পার্সার তুলনা করেছি। তথ্যবহুল সিদ্ধান্ত নিতে আপনি এই উদাহরণগুলি এবং আমার সংক্ষিপ্তসারটি ব্যবহার করতে পারেন। তালিকায় আরও বাস্তবায়ন যুক্ত করতে নির্দ্বিধায় :)


লাইব্রেরিটি দেখে মনে হচ্ছে এটি দুর্দান্ত। তবে, ট্রোলপের সাথে লাইন গণনা তুলনা করা আপত্তিজনক নয় যেহেতু আপনি নির্ভর করে এবং optparse1937 লাইনের কোনটি (দেওয়া বা নেওয়া) তার উপর নির্ভর করে ।
টেলিমাচাস

6
লাইন গণনা তুলনা করা একেবারে ঠিক আছে, যেহেতু optparseএটি একটি পূর্বনির্ধারিত গ্রন্থাগার, অর্থাত্ এটি প্রতিটি রুবি ইনস্টলেশন সহ জাহাজগুলি। Trollopএকটি তৃতীয় পক্ষের গ্রন্থাগার, অতএব আপনি যখনই কোনও প্রকল্পে এটি অন্তর্ভুক্ত করতে চান আপনাকে অবশ্যই সম্পূর্ণ কোডটি আমদানি করতে হবে। opt-optparse সবসময় কেবলমাত্র ~ 70 লাইন প্রয়োজন, যেহেতু optparseইতিমধ্যে রয়েছে।
ফ্লোরিয়ান পিলজ

8

আপনি কেন অপ্টপার্স এড়াতে চান তা আমি পুরোপুরি বুঝতে পেরেছি - এটি খুব বেশি পরিমাণে পেতে পারে। তবে কয়েকটি সুদূর "হালকা" সমাধান রয়েছে (অপ্টপার্সির তুলনায়) যা গ্রন্থাগার হিসাবে আসে তবে একটি একক রত্ন স্থাপনকে উপযুক্ত করে তুলতে যথেষ্ট সহজ।

উদাহরণস্বরূপ, এই OptiFlag উদাহরণটি দেখুন । প্রক্রিয়াজাতকরণের জন্য কয়েকটি লাইন। আপনার কেস অনুসারে সামান্য কাটা একটি উদাহরণ:

require 'optiflag'

module Whatever extend OptiFlagSet
  flag "f"
  and_process!
end 

ARGV.flags.f # => .. whatever ..

আছে কাস্টমাইজড উদাহরণ টন খুব । আমি অন্যটি ব্যবহার করা স্মরণ করছি যা আরও সহজ ছিল, তবে এটি আপাতত আমার হাত থেকে রক্ষা পেয়েছে তবে আমি যদি ফিরে আসি তবে এখানে একটি মন্তব্য যুক্ত করব।


আপনার উত্তরটি নির্দ্বিধায় নির্ধারিত প্রশ্নের সাথে আরও ভাল মানান।
সিজেএস

4

এটি আমি সত্যই, সস্তা ব্যয়গুলির জন্য ব্যবহার করি:

def main
  ARGV.each { |a| eval a }
end

main

সুতরাং আপনি programname foo barএটি চালিয়ে যদি foo কল এবং তারপর বার। এটি নিক্ষেপ স্ক্রিপ্টগুলির জন্য কার্যকর।


3

আপনি এর মতো কিছু চেষ্টা করতে পারেন:

if( ARGV.include( '-f' ) )
  file = ARGV[ARGV.indexof( '-f' ) + 1 )]
  ARGV.delete('-f')
  ARGV.delete(file)
end

3

তোমরা কি ভেবে দেখেছ থর wycats করে? আমি মনে করি এটি অপ্টপার্সের চেয়ে অনেক বেশি পরিষ্কার। আপনার যদি ইতিমধ্যে কোনও স্ক্রিপ্ট লিখিত থাকে তবে এটির ফর্ম্যাট করতে বা এটির জন্য রিফ্যাক্টর করা আরও কিছু কাজ হতে পারে তবে এটি হ্যান্ডলিং বিকল্পগুলি খুব সহজ করে তোলে।

এখানে পড়ুন থেকে উদাহরণ স্নিপেট:

class MyApp < Thor                                                # [1]
  map "-L" => :list                                               # [2]

  desc "install APP_NAME", "install one of the available apps"    # [3]
  method_options :force => :boolean, :alias => :optional          # [4]
  def install(name)
    user_alias = options[:alias]
    if options.force?
      # do something
    end
    # ... other code ...
  end

  desc "list [SEARCH]", "list all of the available apps, limited by SEARCH"
  def list(search = "")
    # list everything
  end
end

কিছু স্বয়ংক্রিয়ভাবে কমান্ড মানচিত্র যেমন:

app install myname --force

এটি রূপান্তরিত হয়:

MyApp.new.install("myname")
# with {'force' => true} as options hash
  1. ক্লাসটিকে একটি বিকল্প ম্যাপারে রূপান্তর করতে থোর থেকে উত্তরাধিকারী
  2. নির্দিষ্ট পদ্ধতিতে অতিরিক্ত অ-বৈধ শনাক্তকারীদের মানচিত্র করুন। এই ক্ষেত্রে, -L তে: তালিকা রূপান্তর করুন
  3. অবিলম্বে নীচে পদ্ধতিটি বর্ণনা করুন। প্রথম প্যারামিটারটি হ'ল ব্যবহারের তথ্য এবং দ্বিতীয় প্যারামিটারের বিবরণ।
  4. কোনও অতিরিক্ত বিকল্প সরবরাহ করুন। এগুলি - এবং - প্যারামগুলি থেকে মার্শাল করা হবে। এই ক্ষেত্রে, একটি --for এবং একটি -f বিকল্প যুক্ত করা হয়।

আমি কমান্ড-ম্যাপিং জিনিসটি পছন্দ করি, যেহেতু একগুচ্ছ সাবকম্যান্ডের একক বাইনারিটি আমি প্রায়শই করি। তবুও, যদিও আপনি 'আলোক' থেকে কিছুটা এগিয়ে গেছেন। একই কার্যকারিতাটি প্রকাশ করার জন্য আপনি কি আরও সহজ উপায় খুঁজে পেতে পারেন? আপনার যদি --helpআউটপুট মুদ্রণের প্রয়োজন না হয় ? "হেড মাইপোগ্রাম.আরবি" হেল্প আউটপুট হলে কী হবে?
সিজেএস

3

এখানে আমার প্রিয় দ্রুত এবং নোংরা বিকল্প পার্সার:

case ARGV.join
when /-h/
  puts "help message"
  exit
when /-opt1/
  puts "running opt1"
end

বিকল্পগুলি নিয়মিত প্রকাশ হয়, সুতরাং "-h" এছাড়াও "--help" এর সাথে মেলে।

পাঠযোগ্য, মনে রাখা সহজ, কোনও বাহ্যিক গ্রন্থাগার এবং ন্যূনতম কোড।


হ্যাঁ এটা হবে. যদি কোনও সমস্যা হয় তবে আপনি আরও রেজেক্স যুক্ত করতে পারেন, উদাহরণস্বরূপ/-h(\b|elp)
এডওয়ার্ডটেক

2

ট্রলোপ বেশ সস্তা।


এটি হবে, < trollop.rubyforge.org >। আমি বরং এটি পছন্দ করি, আমি মনে করি, যদিও আমি সত্যই কোনও লাইব্রেরি খুঁজছিলাম না।
সিজেএস

সত্য, এটি একটি গ্রন্থাগার। যাইহোক, <800 এলওসি তে, এটি একটি খুব নগন্য one gitorious.org/trolop/mainline/blobs/master/lib/trolop.rb
g33kz0r

1
আমি ভাবছিলাম যে আমি যদি "লাইব্রেরি" ব্যবহার করতে যাচ্ছিলাম তবে 30-50 টি লাইন ভাল হবে lines তবে আবার, আমি অনুমান করি একবার আপনি পৃথক কোড পূর্ণ পৃথক ফাইল পেয়েছেন, লাইন গণনার চেয়ে এপিআই নকশা আরও গুরুত্বপূর্ণ। তবুও, আমি নিশ্চিত নই যে আমি এটিকে একটি অফ-স্ক্রিপ্টের মধ্যে অন্তর্ভুক্ত করতে চাই যা আমি কেবল একটি এলোমেলো সিস্টেমে বিন ডিরেক্টরিতে ঝাঁকুনি করতে চাই।
সিজেএস

1
আপনি এটি পিছনের দিকে পেয়েছেন: মূল বিষয়টি হল আরও জটিল স্থাপনার কৌশল না এড়ানো।
সিজেএস

1
আপনি বেশ ভুল, কারণ আপনি যে ব্যক্তি প্রশ্নটি জিজ্ঞাসা করেছেন তার প্রয়োজন এবং উদ্দেশ্যগুলি পুরোপুরি ভুল ব্যাখ্যা করে (বা উপেক্ষা করছেন) আমি আপনাকে সাবধানতার সাথে প্রশ্নটি পুনরায় পড়ার পরামর্শ দিচ্ছি, বিশেষত চূড়ান্ত দুটি পয়েন্ট।
সিজেএস

2

আপনি যদি রত্ন ব্যবহার না করে কী / মান কমান্ডের জন্য একটি সাধারণ কমান্ড লাইন পার্সার চান:

তবে এটি কেবলমাত্র যদি আপনার কাছে সর্বদা কী / মান জোড়া থাকে তবেই কাজ করে।

# example
# script.rb -u username -p mypass

# check if there are even set of params given
if ARGV.count.odd? 
    puts 'invalid number of arguments'
    exit 1
end

# holds key/value pair of cl params {key1 => value1, key2 => valye2, ...}
opts = {} 

(ARGV.count/2).times do |i|
    k,v = ARGV.shift(2)
    opts[k] = v # create k/v pair
end

# set defaults if no params are given
opts['-u'] ||= 'root'

# example use of opts
puts "username:#{opts['-u']} password:#{opts['-p']}"

আপনার যদি 'কোনও পরীক্ষার প্রয়োজন না হয় তবে আপনি কেবল ব্যবহার করতে পারেন:

opts = {} 

(ARGV.count/2).times do |i|
    k,v = ARGV.shift(2)
    opts[k] = v # create k/v pair
end

2

আমি আমার সর্বাধিক স্ক্রিপ্টগুলির শীর্ষে ব্যবহার করি কোড স্নিপেট এখানে:

arghash = Hash.new.tap { |h| # Parse ARGV into a hash
    i = -1                      
    ARGV.map{  |s| /(-[a-zA-Z_-])?([^=]+)?(=)?(.+)?/m.match(s).to_a }
     .each{ |(_,a,b,c,d)| h[ a ? "#{a}#{b}#{c}" : (i+=1) ] =
                             (a ? (c ? "#{d}" : true) : "#{b}#{c}#{d}") 
          }
    [[:argc,Proc.new  {|| h.count{|(k,_)| !k.is_a?(String)}}],
     [:switches, Proc.new {|| h.keys.select{|k| k[0] == '-' }}]
    ].each{|(n,p)| h.define_singleton_method(n,&p) }
}

আমার দ্রুত এবং নোংরা স্ক্রিপ্টগুলিতে অতিরিক্ত ফাইলগুলির প্রয়োজনও ঘৃণা করি। আমার সমাধানটি আপনি যা চেয়েছেন তা প্রায় আমি আমার যে কোনও স্ক্রিপ্টের শীর্ষে কোডের 10 লাইন স্নিপেট আটকান যা কমান্ড লাইনটিকে পার্স করে এবং অবস্থানীয় আরোগুলি এবং একটি হ্যাশ অবজেক্টে স্যুইচ করে (সাধারণত কোনও বস্তুর জন্য বরাদ্দ করা হয় যা আমি আরগ্যাশের নাম রেখেছি) এবং নীচের উদাহরণগুলিতে )।

এখানে একটি উদাহরণ কমান্ড লাইন যা আপনি পার্স করতে চাইতে পারেন ...

./myexampleprog.rb -s -x=15 --longswitch arg1 --longswitch2=val1 arg2

যা এটির মতো হ্যাশ হয়ে উঠবে।

 { 
   '-s' => true, 
   '-x=' => '15', 
   '--longswitch' => true, 
   '--longswitch2=' => 'val1', 
   0 => 'arg1', 
   1 => 'arg2'
 }

এগুলি ছাড়াও, দুটি সুবিধাজনক পদ্ধতি হ্যাশটিতে যুক্ত করা হয়েছে:

  • argc() সুইচবিহীন আর্গুমেন্টগুলির গণনা ফিরিয়ে দেবে।
  • switches() উপস্থিত থাকা স্যুইচগুলির জন্য কীগুলি সমেত একটি অ্যারের ফিরিয়ে দেবে

এটি কিছু দ্রুত এবং নোংরা জিনিস যেমন ...

  • যাচাই করুন সুইচগুলি পাস না করেই আমি সঠিক সংখ্যাগত অবস্থানগত আর্গুমেন্ট পেয়েছি ( arghash.argc == 2 )
  • অবস্থানগত আর্গুমেন্টগুলির (যেমন arghash[1]সর্বদা দ্বিতীয় নন-স্যুইচ যুক্তিটি পাওয়া যায়) সাথে আলাদা হয়ে যাওয়া বা ভিন্ন ভিন্ন হওয়া ছাড়া তাদের আপেক্ষিক অবস্থানের দ্বারা অবস্থানগত তর্কগুলি অ্যাক্সেস করুন ।
  • কমান্ড লাইনে যেমন "--max = 15" তে সমর্থন মান-নির্ধারিত সুইচগুলি arghash['--max=']উদাহরণস্বরূপ কমান্ড লাইনটি দিয়ে '15' এর মান দেয় যার মাধ্যমে অ্যাক্সেস করা যায় ।
  • খুব সাধারণ স্বরলিপি ব্যবহার করে কমান্ড লাইনে একটি স্যুইচের উপস্থিতি বা অনুপস্থিতির জন্য পরীক্ষা করুন যেমন arghash['-s']উপস্থিত থাকে কিনা তা সত্য বলে মূল্যায়ন করে এবং যদি এটি অনুপস্থিত থাকে তবে শূন্য হয়।
  • এর মতো সেট ক্রিয়াকলাপগুলি ব্যবহার করে একটি স্যুইচ বা সুইচের বিকল্পগুলির উপস্থিতি পরীক্ষা করুন

    puts USAGETEXT if !(%w(-h --help) & arghash.switches()).empty?

  • সেট অপারেশনগুলি ব্যবহার করে অবৈধ স্যুইচগুলির ব্যবহার সনাক্ত করুন

    puts "Invalid switch found!" if !(arghash.switches - %w(-valid1 -valid2)).empty?

  • একটি সাধারণ ব্যবহার করে নিখুঁত যুক্তিগুলির জন্য ডিফল্ট মান উল্লেখ করুন Hash.merge()যেমন নীচের উদাহরণ যা -max = এর জন্য একটি মান পূরণ করে এবং যদি সেট করা না হয় তবে 4 তম অবস্থানগত যুক্তি যুক্ত করে।

    with_defaults = {'-max=' => 20, 3 => 'default.txt'}.merge(arghash)


(কোডটি ফরম্যাটিংয়ের উন্নতি করার জন্য আমি এটি সম্পাদনা করেছি, প্রধানত ব্লক এবং নিয়ন্ত্রণ কাঠামোটিকে আরও সুস্পষ্ট করার জন্য প্রান্তিককরণ ব্যবহার করে, যা আমার মনে হয় বিশেষভাবে এটি বিশিষ্টতা সহ এই ঘন কিছুতে গুরুত্বপূর্ণ। তবে আপনি যদি নতুন বিন্যাসকে ঘৃণা করেন তবে দয়া করে নির্দ্বিধায় অনুভব করুন সম্পাদনাটি পূর্বাবস্থায়
ফেলার জন্য

এটি পড়ার জন্য বিশ্বের সহজতম জিনিস না হলে এটি বেশ সুন্দর। আমি এটি পছন্দ করি যে এটি যুক্তি "সিনট্যাক্স" পরিবর্তন করে (এখানে, অবস্থানগত আরগগুলির পরে বিকল্পগুলি মঞ্জুরি দেয় এবং ব্যবহার ব্যতীত বিকল্প যুক্তিগুলি অস্বীকার করে =) আপনার প্রয়োজনীয় কোডটিতে পার্থক্য আনতে পারে।
সিজেএস

পুনর্নির্মাণের জন্য ধন্যবাদ। এটি অবশ্যই পড়া অস্পষ্ট এবং স্বচ্ছতার জন্য কোডের দৈর্ঘ্য সহজেই বাণিজ্য করা যায়। এখন যেহেতু আমি এই কোডটিকে কমবেশি বিশ্বাস করি, আমি এটিকে একটি রত্নের মতো ব্যবহার করি এবং আমি কখনই এটি কভারগুলির অধীনে কী করছে তা অনুধাবন করার চেষ্টা করি না (সুতরাং স্পষ্টতা এখন আর গুরুত্বপূর্ণ নয় যে আমার বিশ্বাস আছে)।
ডেভিড ফস্টার 21

1

এটি গ্রহণযোগ্য উত্তরের সাথে খুব মিল, তবে ARGV.delete_ifযা আমি ব্যবহার করি তা আমার সাধারণ পার্সারে ব্যবহার করি । একমাত্র আসল পার্থক্য হ'ল আর্গুমেন্ট সহ বিকল্পগুলি অবশ্যই একসাথে থাকতে হবে (উদাঃ -l=file)।

def usage
  "usage: #{File.basename($0)}: [-l=<logfile>] [-q] file ..."
end

$quiet = false
$logfile = nil

ARGV.delete_if do |cur|
  next false if cur[0] != '-'
  case cur
  when '-q'
    $quiet = true
  when /^-l=(.+)$/
    $logfile = $1
  else
    $stderr.puts "Unknown option: #{cur}"
    $stderr.puts usage
    exit 1
  end
end

puts "quiet: #{$quiet} logfile: #{$logfile.inspect} args: #{ARGV.inspect}"

0

স্পষ্টতই @ উইলিয়ামমর্গান এবং আমি একই মত চিন্তা করি। আমি শুধু গিটহাব থেকে গত রাতে মুক্তি কি আমি এখন দেখতে যত্নহীন একটি অনুরূপ লাইব্রেরী (নামযুক্ত কিভাবে?) GitHub থেকে OptionParser জন্য একটি অনুসন্ধান সম্পন্ন করার পর, দেখতে সুইচ

কয়েকটি পার্থক্য আছে, কিন্তু দর্শন একই। একটি সুস্পষ্ট পার্থক্য হ'ল সুইচগুলি অপশনপার্সারের উপর নির্ভরশীল।


0

আমি আমার নিজস্ব বিকল্প পার্সার রত্নটি বিকাশ করছি যার নাম অ্যাক্লেইম

আমি এটি লিখেছিলাম কারণ আমি গিট স্টাইলের কমান্ড লাইন ইন্টারফেস তৈরি করতে চেয়েছিলাম এবং প্রতিটি কমান্ডের কার্যকারিতা পৃথক শ্রেণিতে আলাদা করে রাখতে সক্ষম হয়েছি, তবে এটি সম্পূর্ণ কমান্ড কাঠামো ছাড়াও ব্যবহার করা যেতে পারে:

(options = []) << Acclaim::Option.new(:verbose, '-v', '--verbose')
values = Acclaim::Option::Parser.new(ARGV, options).parse!
puts 'Verbose.' if values.verbose?

এখনও পর্যন্ত কোনও স্থিতিশীল মুক্তি নেই, তবে আমি ইতিমধ্যে কিছু বৈশিষ্ট্যগুলি প্রয়োগ করেছি:

  • কাস্টম বিকল্প পার্সার
  • বিকল্পের যুক্তিগুলির নমনীয় বিশ্লেষণ যা ন্যূনতম এবং alচ্ছিক উভয়ের জন্য মঞ্জুরি দেয়
  • অনেক বিকল্প শৈলীর জন্য সমর্থন
  • একই বিকল্পের একাধিক উদাহরণ প্রতিস্থাপন, সংযোজন বা উত্থাপন করুন
  • কাস্টম বিকল্প হ্যান্ডলারগুলি
  • কাস্টম টাইপ হ্যান্ডলার
  • সাধারণ স্ট্যান্ডার্ড গ্রন্থাগার ক্লাসের জন্য পূর্বনির্ধারিত হ্যান্ডলারগুলি

কমান্ডগুলিতে প্রচুর জোর রয়েছে তাই সাধারণ কমান্ড লাইন পার্সিংয়ের জন্য এটি কিছুটা ভারী হতে পারে তবে এটি ভালভাবে কাজ করে এবং আমি আমার সমস্ত প্রকল্পে এটি ব্যবহার করছি। আপনি যদি কমান্ড ইন্টারফেসের দিকটিতে আগ্রহী হন তবে আরও তথ্য এবং উদাহরণের জন্য প্রকল্পের গিটহাব পৃষ্ঠাটি দেখুন।


1
আমি অত্যন্ত প্রশংসা করি সুপারিশ। এটি ব্যবহার করা সহজ এবং আপনার প্রয়োজনীয় সমস্ত অপশন রয়েছে।
বোলসারেন্সিয়র

0

মনে করুন কোনও কমান্ডের সর্বাধিক একটি ক্রিয়া এবং স্বেচ্ছাচারী সংখ্যক বিকল্প রয়েছে:

cmd.rb
cmd.rb action
cmd.rb action -a -b ...
cmd.rb action -ab ...

বৈধতা ছাড়াই পার্সিং এর মত হতে পারে:

ACTION = ARGV.shift
OPTIONS = ARGV.join.tr('-', '')

if ACTION == '***'
  ...
  if OPTIONS.include? '*'
    ...
  end
  ...
end

0

https://github.com/soveran/clap

other_args = Clap.run ARGV,
  "-s" => lambda { |s| switch = s },
  "-o" => lambda { other = true }

46LOC (1.0.0 এ), বাহ্যিক বিকল্প পার্সারের উপর নির্ভরতা নেই। কাজ হয়ে যায়। সম্ভবত অন্যের মতো সম্পূর্ণ বৈশিষ্ট্যযুক্ত নয়, তবে এটি 46 ব্লক।

আপনি যদি কোডটি পরীক্ষা করেন তবে আপনি অন্তর্নিহিত কৌশলটি খুব সহজেই অনুলিপি করতে পারেন - ল্যাম্বডাস নির্ধারণ করুন এবং যথাযথ সংখ্যাটি নিশ্চিত করার জন্য খাঁটিটি ব্যবহার করুন যদি আপনি সত্যিকার অর্থে কোনও বাহ্যিক গ্রন্থাগার না চান তবে পতাকাটি অনুসরণ করে।

সহজ। সস্তা।


সম্পাদনা করুন : অন্তর্নিহিত ধারণাটি সেদ্ধ হয়ে গেছে কারণ আমি মনে করি আপনি যুক্তিসঙ্গত কমান্ড লাইন পার্সার তৈরি করতে কোনও স্ক্রিপ্টে এটি অনুলিপি / আটকে দিতে পারেন। এটি অবশ্যই স্মৃতির প্রতিশ্রুতিবদ্ধ এমন কিছু নয় , তবে ল্যাম্বা আরটিটি সস্তা পার্সার হিসাবে ব্যবহার করা একটি অভিনব ধারণা:

flag = false
option = nil
opts = {
  "--flag" => ->() { flag = true },
  "--option" => ->(v) { option = v }
}

argv = ARGV
args = []

while argv.any?
  item = argv.shift
  flag = opts[item]

  if flag
    raise ArgumentError if argv.size < arity
    flag.call(*argv.shift(arity))
  else
    args << item
  end
end

# ...do stuff...

প্রশ্নের শেষে পয়েন্ট 1 পড়ুন দয়া করে। আপনি যদি এখানে আপনার উত্তরে সমস্ত প্রয়োজনীয় কোড টাইপ করতে না পারেন তবে এটি প্রশ্নের উত্তর নয়।
সিজেএস

ভাল যুক্তি! আমি মনে করি যে সময় আমি ধারণা করেছি যে এই লিবটি যথেষ্ট ছোট ছিল যে আপনি ডাব্লু / ও এর বাহ্যিক নির্ভরতার প্রয়োজনের জন্য যা কিছু স্ক্রিপ্টে কাজ করছেন তা পুরো জিনিসটি অনুলিপি / পেস্ট করতে পারবেন তবে এটি অবশ্যই স্মৃতিতে প্রতিশ্রুতিবদ্ধ একটি পরিষ্কার ওয়ান-লাইনার নয় আপনার বক্তব্য # 2 পূরণ করতে। আমি মনে করি অন্তর্নিহিত ধারণাটি উপন্যাস এবং যথেষ্ট শীতল যে আমি এগিয়ে গিয়ে একটি সেদ্ধ ডাউন সংস্করণ তৈরি করেছি যা আপনার প্রশ্নের উত্তরকে আরও কিছুটা যথাযথভাবে জবাব দেয়।
বেন আলাভি

-1

আমি আমার নিজস্ব সহজ বিকল্প পার্সার ভাগ করতে চলেছি যা আমি কিছু সময়ের জন্য কাজ করছি। এটি কেবল of৪ টি লাইনের কোড এবং এটি গিটের অভ্যন্তরীণ বিকল্প পার্সার কী করে তার মূল কথাগুলি। আমি অপশনপার্সারকে অনুপ্রেরণা হিসাবে গ্রহণ করেছি এবং গিটেরও।

https://gist.github.com/felipec/6772110

দেখে মনে হচ্ছে:

opts = ParseOpt.new
opts.usage = "git foo"

opts.on("b", "bool", help: "Boolean") do |v|
 $bool = v
end

opts.on("s", "string", help: "String") do |v|
 $str = v
end

opts.on("n", "number", help: "Number") do |v|
 $num = v.to_i
end

opts.parse

আপনি কোডটিও পরীক্ষা করেননি। পার্সিং কোডটি বের করে আমি আরও একটি উত্তর রেখেছি।
ফেলিপিসি

আমার এটি দেওয়ার দরকার নেই যে আপনি বলেছিলেন যে এটি 74 লাইন দীর্ঘ long যাইহোক, আমি এখনই এটি দেখেছি এবং এটি এখনও প্রয়োজনীয়তার প্রথম বাক্যটি লঙ্ঘন করে This (এই প্রতিক্রিয়াটি স্ট্যাক ওভারফ্লো কনভেনশন লঙ্ঘন করে যে আপনার সাইটের কোনও অফ-সাইট লিঙ্ক দেওয়ার পরিবর্তে আপনার উত্তরটিতে কোড অন্তর্ভুক্ত করা উচিত))
সিজেএস

-1

EasyOptions এ কোনও বিকল্প পার্সিং কোডের প্রয়োজন হয় না। সাহায্যের পাঠ্যটি লিখুন, প্রয়োজনীয় হয়ে গেছে।

## Options:
##   -i, --interactive  Interactive mode
##   -q, --quiet        Silent mode

require 'easyoptions'
unless EasyOptions.options[:quiet]
    puts 'Interactive mode enabled' if EasyOptions.options[:interactive]
    EasyOptions.arguments.each { |item| puts "Argument: #{item}" }
end

EasyOptions বিবৃতি প্রয়োজন ছাড়াই একটি একক রুবি ফাইল, এবং এগুলি মনে রাখার মতো কোনও পার্সিং কোড নেই। মনে হচ্ছে এর পরিবর্তে আপনি এম্বেডযোগ্য এমন কিছু চান যা স্মরণ করার জন্য যথেষ্ট শক্তিশালী।
রেনাটো সিলভা 13
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.