Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी में कमांड-लाइन ऐप्स लिखना

हालांकि छोटी उपयोगी स्क्रिप्ट लिखना मजेदार है, लेकिन कभी-कभी आपको ईश्वर के प्रति ईमानदार कमांड-लाइन एप्लिकेशन लिखने की आवश्यकता होती है। एक जो तर्क लेता है और इनपुट, आउटपुट, त्रुटि रिपोर्टिंग, आदि के लिए यूनिक्स सम्मेलनों के साथ अच्छी तरह से खेलता है।

सौभाग्य से, रूबी आपको उन सभी बिल्डिंग ब्लॉक्स देता है जिनकी आपको कमांड-लाइन एप्लिकेशन को काफी आसानी से आवश्यकता होती है। इस पोस्ट में मैं विशिष्ट "हाउ टू डू एक्स विद जेम वाई" दृष्टिकोण से आगे जाने की उम्मीद करता हूं, और इसके बजाय उन सभी टुकड़ों का व्यापक अवलोकन करता हूं जो एक प्रथम-दर कमांड-लाइन ऐप बनाने के लिए एक साथ जाते हैं।

इनपुट:पर्यावरण चर

पर्यावरण चर आमतौर पर छोटे कॉन्फ़िगरेशन मानों के लिए उपयोग किए जाते हैं जिन्हें आप थोड़ी देर के लिए चिपकाना चाहते हैं। एपीआई कुंजियाँ एक अच्छा उदाहरण हैं।

पर्यावरण चर सेट करना

उपयोगकर्ता आमतौर पर बैश जैसे शेल के माध्यम से पर्यावरण चर सेट करते हैं। वे उन्हें एक विशिष्ट सत्र के लिए सेट कर सकते हैं:

$ AWS_ACCESS_KEY_ID=FOO

वे उन्हें वर्तमान सत्र के साथ-साथ किसी भी नए बैश सत्र के लिए सेट कर सकते हैं:

$ export AWS_ACCESS_KEY_ID=FOO

या वे उन्हें एक ही कार्यक्रम के लिए सेट कर सकते हैं:

$ env AWS_ACCESS_KEY_ID=FOO aws s3 mb s3://mybucket

पर्यावरण चर पढ़ना

भले ही उपयोगकर्ता पर्यावरण चर कैसे सेट करता है, आप इसे रूबी के ENV . के माध्यम से पढ़ सकते हैं हैश।

key_id = ENV["AWS_ACCESS_KEY_ID"]

पर्यावरण संस्करण हुड के नीचे कैसे काम करते हैं?

प्रत्येक प्रक्रिया में इसके साथ जुड़े पर्यावरण चर की एक तालिका होती है। जब यह बाल प्रक्रियाओं को जन्म देता है, तो माता-पिता जो भी बदलाव करना चाहते हैं, उसके साथ उन्हें उस तालिका की एक प्रति प्राप्त होती है।

कीचड़ की तरह साफ?

अधिक पठनीय स्पष्टीकरण के लिए, मेरी अन्य ब्लॉग पोस्ट देखें:द रूबीस्ट्स गाइड टू एनवायरनमेंट वेरिएबल्स।

कमांड-लाइन तर्क

जब आप टर्मिनल में कोई प्रोग्राम चलाते हैं तो कमांड-लाइन तर्क प्रोग्राम के नाम के बाद आप जो कुछ भी डालते हैं:

$ echo foo bar baz

उपरोक्त उदाहरण में "फू", "बार" और "बाज" सभी कमांड लाइन तर्क हैं।

एक अधिक यथार्थवादी उदाहरण इस तरह दिख सकता है:

$ honeybadger deploy -v --environment staging

लेकिन यहां भी, कमांड-लाइन तर्क सिर्फ टेक्स्ट हैं। अगर हम चाहते हैं --environment staging से मतलब कुछ भी, हमें खुद ही इसका पता लगाना होगा।

आदेश-पंक्ति तर्क भेजना

हम पहले ही इस तरह भेजे गए तर्क देख चुके हैं:

$ echo foo bar baz

लेकिन चूंकि रूबी एक व्याख्या की गई भाषा है, इसलिए आपको कुछ इस तरह का भी सामना करना पड़ सकता है:

$ ruby myprog.rb foo

जहां तक ​​ओएस का संबंध है, आप "रूबी" नामक एक प्रोग्राम चला रहे हैं और इसे दो तर्क दे रहे हैं।

सौभाग्य से, रूबी यह जानने के लिए काफी स्मार्ट है कि तर्क "फू" आपके प्रोग्राम के लिए है, रूबी के लिए नहीं। तो आपके प्रोग्राम को एक तर्क दिखाई देगा, "foo"

कमांड-लाइन तर्क पढ़ना

कमांड-लाइन तर्क ARGV . नामक एक सरणी में संग्रहीत होते हैं . यह एक वैश्विक चर है, इसलिए आप इसे अपने कार्यक्रम में कहीं से भी एक्सेस कर सकते हैं।

नीचे दिए गए उदाहरण में, हम सब कुछ ARGV . में प्रिंट कर रहे हैं . बेझिझक इसे अपने टर्मिनल में कॉपी और पेस्ट करें और इसके साथ थोड़ा खेलें।

$ ruby -e "puts ARGV.inspect" foo bar baz
["foo", "bar", "baz"]
<ब्लॉकक्वॉट>

कृपया ruby -e . द्वारा फेंके न जाएं व्यापार। मैं इसे यहाँ केवल इसलिए उपयोग कर रहा हूँ क्योंकि यह मुझे प्रोग्राम और इसे एक ही पंक्ति में चलाने का परिणाम दिखाने देता है।

आदेश-पंक्ति तर्क पार्स करना

कमांड लाइन तर्क सिर्फ पाठ हैं। अगर आप चाहते हैं कि टेक्स्ट का मतलब मतलब . हो कुछ भी, आपको इसे पार्स करना होगा। सौभाग्य से, कई अच्छे पुस्तकालय हैं जो पार्सिंग में आपकी सहायता कर सकते हैं।

इन वर्षों में, कमांड-लाइन तर्कों के लिए कुछ हद तक मानक वाक्यविन्यास उभरा है। यह कुछ इस तरह दिखता है:

$ program -a --option foo

इस शैली से आप -h . जैसे बूलियन फ़्लैग प्राप्त कर सकते हैं मदद प्रदर्शित करने के लिए। यह आपको मानों के साथ विकल्प निर्दिष्ट करने देता है।

पेश है OptionParser

OptionParser कक्षा रूबी की मानक पुस्तकालय का हिस्सा है। यह आपको ऊपर की शैली से मेल खाने वाले विकल्पों को पार्स करने का एक आसान तरीका देता है।

आइए एक सरल एप्लिकेशन बनाते हैं जो हैलो कहता है। यह आपको कमांड-लाइन तर्क के माध्यम से नाम निर्दिष्ट करने देगा।

require 'optparse'

# This will hold the options we parse
options = {}

OptionParser.new do |parser|

  # Whenever we see -n or --name, with an
  # argument, save the argument.
  parser.on("-n", "--name NAME", "The name of the person to greet.") do |v|
    options[:name] = v
  end
end.parse!

# Now we can use the options hash however we like.
puts "Hello #{ options[:name] }"  if options[:name]

फिर जब मैं इसे चलाता हूं, यह बस काम करता है:

$ ruby hello.rb --name Starr
Hello Starr

$ ruby hello.rb -n Starr
Hello Starr

"सहायता" स्क्रीन जोड़ना

सहायता सुविधा जोड़ना उतना ही आसान है। हमें बस कुछ टेक्स्ट देना है, और -h . के लिए एक कमांड जोड़ना है :

OptionParser.new do |parser|
  parser.banner = "Usage: hello.rb [options]"

  parser.on("-h", "--help", "Show this help message") do ||
    puts parser
  end

  ...
end.parse!

अब हम मदद मांग सकते हैं:

$ ruby hello.rb -h
Usage: hello.rb [options]
    -h, --help                       Show this help message
    -n, --name NAME                  The name of the person to greet.

टाइपकास्टिंग तर्क

सभी कमांड-लाइन तर्क तार हैं, लेकिन कभी-कभी आप चाहते हैं कि उपयोगकर्ता आपको एक नंबर या एक तिथि दे। हाथ से रूपांतरण करना कठिन हो सकता है, इसलिए OptionParser यह आपके लिए करता है।

नीचे दिए गए उदाहरण में, मैं एक "गिनती" विकल्प जोड़ने जा रहा हूं जो उपयोगकर्ता को यह निर्दिष्ट करने देता है कि प्रोग्राम को कितनी बार हैलो कहना चाहिए। मैं बता रहा हूँ OptionParser एक Integer . पर डालने के लिए , जो यह करता है।

OptionParser.new do |parser|

  ...

  # Note the `Integer` arg. That tells the parser to cast the value to an int.
  # I could have used `Float`, `Date`, or a number of other types.
  parser.on("-c", "--count COUNT", Integer, "Repeat the message COUNT times") do |v|
    options[:count] = v
  end

end.parse!

if options[:name]
  options.fetch(:count, 1).times do
    puts "Hello #{ options[:name] }"
  end
end

अब, जब मैं प्रोग्राम चलाता हूं तो मुझे कई बार बधाई दी जाती है:

$ ruby hello.rb -n Starr -c 5
Hello Starr
Hello Starr
Hello Starr
Hello Starr
Hello Starr

नामकरण परंपराएं

प्रोग्रामिंग के सबसे कठिन पहलुओं में से एक यह पता लगाना हो सकता है कि चीजों को क्या नाम देना है। कमांड-लाइन तर्क कोई अपवाद नहीं हैं। आपकी सहायता के लिए, मैंने सामान्य तर्कों और उनके अर्थों की एक छोटी तालिका संकलित की है:

ध्वज सामान्य अर्थ
-a सभी, संलग्न करें
-d डीबग मोड, या निर्देशिका निर्दिष्ट करें
-e कुछ निष्पादित करें, या इसे संपादित करें
-f फ़ाइल निर्दिष्ट करें, या किसी कार्रवाई को बाध्य करें।
-h सहायता
-m संदेश निर्दिष्ट करें
-o कोई आउटपुट फ़ाइल या डिवाइस निर्दिष्ट करें
-q शांत मोड
-v वर्बोज़ मोड। वर्तमान संस्करण प्रिंट करें
-y किसी भी संकेत के लिए "हां" कहें

OptionParser के विकल्प

OptionParser अच्छा है, लेकिन इसकी सीमाएं हैं। सबसे स्पष्ट रूप से, यह कमांड-आधारित सिंटैक्स का समर्थन नहीं करता है जो हाल के वर्षों में लोकप्रिय हो गए हैं:

$ myprog command subcommand -V

सौभाग्य से, एक टन . हैं वहाँ से बाहर पुस्तकालयों को पार्स करने का विकल्प। मुझे यकीन है कि आप अपनी पसंद का एक ढूंढ पाएंगे। यहां तीन हैं जो दिलचस्प लग रही हैं:

  • GLI - "Git-like Interface" कमांड-लाइन पार्सर आपको आसानी से ऐसे एप्लिकेशन बनाने की अनुमति देता है, जो git की तरह, कई कमांड के साथ एकल निष्पादन योग्य हैं।
  • CRI - नेस्टेड कमांड के समर्थन के साथ कमांड-लाइन टूल बनाने के लिए उपयोग में आसान लाइब्रेरी।
  • मेथाडोन - मेथाडोन डीएसएल को पार्स करने का अपना विकल्प प्रदान करता है, लेकिन यह उससे कहीं आगे जाता है। यह आपके लिए एक निर्देशिका संरचना, एक परीक्षण सूट और लॉगिंग स्थापित करेगा। यह आपके सीएलआई के लिए रेल की तरह है।

STDIN के साथ बड़ी मात्रा में डेटा इनपुट करना

बड़ी मात्रा में डेटा इनपुट करने के लिए कमांड-लाइन तर्क उपयुक्त नहीं हैं। उसके लिए, आप एक IO स्ट्रीम का उपयोग करना चाहेंगे। और STDIN सबसे सुविधाजनक IO स्ट्रीम में से एक है।

अधिकांश प्रोग्रामों को ऑपरेटिंग सिस्टम द्वारा स्वचालित रूप से एक एसटीडीआईएन सौंपा जाएगा। यह केवल-पढ़ने के लिए फ़ाइल की तरह है जिसका उपयोग OS आपके ऐप डेटा को भेजने के लिए करता है। इसका उपयोग उपयोगकर्ता से कीबोर्ड इनपुट प्राप्त करने के लिए किया जा सकता है। लेकिन इससे भी महत्वपूर्ण बात यह है कि इसका उपयोग पाइप के माध्यम से अन्य कार्यक्रमों से डेटा प्राप्त करने के लिए किया जा सकता है।

आप एसटीडीआईएन का उपयोग वैसे ही करते हैं जैसे आप केवल-पढ़ने के लिए फ़ाइल का उपयोग करते हैं। यहाँ, मैं अपने प्रोग्राम के STDIN में कुछ टेक्स्ट डाल रहा हूँ। फिर मैं read . का उपयोग करता हूं इसे लाने की विधि।

$ echo "hello world" | ruby -e "puts STDIN.read.upcase"
HELLO WORLD

रूबी में, आप Enumerable . का उपयोग कर सकते हैं आईओ वस्तुओं पर सुविधाएँ। और एसटीडीआईएन कोई अपवाद नहीं है। इसका मतलब है कि आप हर तरह के टोटके कर सकते हैं:

# Get the first 20 lines
STDIN.first(20)

# Convert to integers and reject odds
STDIN.map(&:to_i).reject(&:odd)

...etc

परिणामों को STDOUT में आउटपुट करना

STDOUT केवल लिखने के लिए IO स्ट्रीम है जिसे ऑपरेटिंग सिस्टम आपके प्रोग्राम को असाइन करता है।

STDOUT को लिखकर आप यूजर के टर्मिनल पर टेक्स्ट भेज सकते हैं। उपयोगकर्ता आउटपुट को किसी फ़ाइल में रीडायरेक्ट कर सकता है, या इसे किसी अन्य प्रोग्राम में पाइप कर सकता है।

आप STDOUT का उपयोग वैसे ही करेंगे जैसे आप किसी अन्य केवल-लिखने वाली फ़ाइल का उपयोग करते हैं:

STDOUT.write("Hi!\n")
# hi

और हां, puts और print दोनों आउटपुट STDOUT को।

STDERR को स्थिति की जानकारी भेजना

STDERR अभी तक केवल लिखने के लिए IO स्ट्रीम है। यह सामान्य आउटपुट के लिए नहीं है। यह विशेष रूप से स्थिति संदेशों के लिए है — इसलिए वे वास्तविक . के रास्ते में नहीं आते हैं आउटपुट।

एसटीडीईआरआर आमतौर पर उपयोगकर्ता के टर्मिनल में प्रदर्शित किया जाएगा, भले ही वे एसटीडीओयूटी को किसी फ़ाइल या किसी अन्य प्रोग्राम पर रीडायरेक्ट कर रहे हों।

नीचे दिए गए उदाहरण में हम वेबपेज लाने के लिए कर्ल का उपयोग कर रहे हैं। यह वेबपेज की सामग्री को STDOUT में आउटपुट करता है, और प्रगति की जानकारी STDERR को प्रदर्शित करता है:

$ curl "https://www.google.com/" > /tmp/g.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  151k    0  151k    0     0   277k      0 --:--:-- --:--:-- --:--:--  277k

अपने स्वयं के कार्यक्रमों से एसटीडीईआरआर को लिखना आसान है। बस इसे IO ऑब्जेक्ट की तरह मानें:

STDERR.write("blah\n")
STDERR.puts("blah")

सुंदर स्टिक से मारना

अब तक हमने जो उदाहरण देखे हैं, वे किसी भी डिज़ाइन पुरस्कार को जीतने वाले नहीं हैं। लेकिन इसका कोई कारण नहीं है कि कमांड-लाइन ऐप्स बदसूरत, या गैर-संवादात्मक हों।

यदि आप अपने ऐप को बेहतर बनाने का निर्णय लेते हैं, तो भारी भारोत्तोलन करने के लिए बहुत सारे शानदार रत्न हैं। यहां तीन हैं जो मुझे पसंद हैं:

  • हाईलाइन - हाईलाइन एक बेहतरीन लाइब्रेरी है जो उपयोगकर्ता इनपुट को इकट्ठा करने, मान्य करने और टाइपकास्ट करने में बहुत काम लेती है।
  • command_line_reporter - ASCII प्रगति रिपोर्ट बनाना आसान बनाता है।
  • पेंट - आपको अपने उबाऊ पुराने टेक्स्ट को रंगीन करने के लिए आसानी से एएनएसआई रंग कोड जोड़ने देता है।

अधिक विस्तृत सूची देखें

निकास स्थिति

यदि आपका प्रोग्राम किसी त्रुटि के साथ बाहर निकलता है, तो आपको ओएस को एक्जिट कोड के माध्यम से बताना चाहिए। यही कारण है कि इस तरह से बैश कोड काम करना संभव बनाता है:

$ prog1 && prog2

यदि आप बैश के && . से परिचित नहीं हैं ऑपरेटर, इसका सीधा सा अर्थ है "prog2 तभी चलाएं जब prog1 सफलतापूर्वक बाहर निकल जाए।"

रूबी डिफ़ॉल्ट रूप से "सफलता" कोड और अपवाद पर "विफलता" कोड के साथ बाहर निकलती है। बाकी सब कुछ लागू करने के लिए आप पर निर्भर है। सौभाग्य से, यह आसान है:

# Any nonzero argument to `exit` counts as failure
exit(1)

अधिक जानकारी के लिए, मेरी अन्य पोस्ट देखें कि रूबी प्रोग्राम से कैसे बाहर निकलें।

प्रक्रिया का नाम सेट करना

यदि आपका कमांड-लाइन प्रोग्राम थोड़ी देर के लिए चलने वाला है, तो यह महत्वपूर्ण है कि लोगों को पता चले कि सिस्टम प्रक्रियाओं को सूचीबद्ध करते समय यह क्या है। आम तौर पर, रूबी प्रोग्राम प्रोसेस नाम में वह सब कुछ होता है जिसे आपने प्रोग्राम चलाने के लिए टाइप किया था। तो अगर आपने ruby myapp -v . टाइप किया है , यह प्रक्रिया का नाम है।

यदि आपके प्रोग्राम में बहुत सारे तर्क हैं, तो यह अपठनीय हो सकता है। तो हो सकता है कि आप एक अधिक अनुकूल प्रक्रिया नाम सेट करना चाहें। आप इसे इस तरह कर सकते हैं:

Process.setproctitle("My Awesome Command Line App")

यदि आप अच्छा महसूस कर रहे हैं, तो आप प्रक्रिया शीर्षक का उपयोग उपयोगकर्ता को इस बारे में जानकारी देने के लिए कर सकते हैं कि प्रक्रियाएँ किसी भी समय क्या कर रही हैं।

Process.setproctitle("Mail Sender: initializing")
init(...)
Process.setproctitle("Mail Sender: connecting")
connect(...)
Process.setproctitle("Mail Sender: sending")
send(...)

अधिक जानकारी के लिए, मेरी पोस्ट देखें:अपनी रूबी स्क्रिप्ट की प्रक्रिया का नाम कैसे बदलें जैसा कि शीर्ष और पीएस द्वारा दिखाया गया है


  1. रूबी के साथ कमांड-लाइन एप्लिकेशन (सीएलआई) कैसे बनाएं?

    बहुत से लोग भूल जाते हैं कि रूबी ऐसे काम कर सकती है जो वेब एप्लिकेशन नहीं हैं। इस लेख में, मैं आपको दिखाना चाहता हूं कि इसका समाधान करने में मदद के लिए एक कमांड-लाइन एप्लिकेशन कैसे बनाया जाए! यहां कुछ कमांड-लाइन एप्लिकेशन दिए गए हैं जिनसे आप परिचित हो सकते हैं: psql rails bundler gem git कम

  1. रूबी में 9 नई सुविधाएँ 2.6

    रूबी का एक नया संस्करण नई सुविधाओं और प्रदर्शन में सुधार के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज रूबी 2.5 और पुराने संस्करण पहले से ही अंतहीन श्रेणी के एक रूप का समर्थन करते हैं (Float::INFINITY के साथ) ), लेकिन रूबी 2.6 इसे अगले स्तर पर ले

  1. iPad के लिए 8 सर्वश्रेष्ठ लेखन ऐप्स

    कीबोर्ड अटैचमेंट वाला iPad सुपर पोर्टेबल और आसान होने के कारण एक संपूर्ण लेखन सेटअप बनाता है। इस समीकरण का एक महत्वपूर्ण हिस्सा आपके द्वारा उपयोग किया जाने वाला लेखन कार्यक्रम है। जबकि iPad वर्ड प्रोसेसिंग के लिए उपयोग करने के लिए पूरी तरह से स्वीकार्य पेज ऐप के साथ आता है, वहाँ कई विकल्प हैं जिन्हे