बैश लिपि में पास किए गए तर्कों की संख्या जांचें


726

मैं अपने बैश स्क्रिप्ट को एक त्रुटि संदेश प्रिंट करना चाहूंगा यदि आवश्यक तर्क गिनती पूरी नहीं हुई है।

मैंने निम्नलिखित कोड आज़माया:

#!/bin/bash
echo Script name: $0
echo $# arguments 
if [$# -ne 1]; 
    then echo "illegal number of parameters"
fi

किसी अज्ञात कारण से मुझे निम्नलिखित त्रुटि मिली है:

test: line 4: [2: command not found

मैं क्या गलत कर रहा हूं?


54
आपको अपनी स्क्रिप्ट का नाम नहीं देना चाहिए test। यह एक मानक यूनिक्स कमांड का नाम है, आप इसे छाया नहीं देना चाहेंगे।
बारमर

20
हमेशा '' '' ('' ['') या '(' (')' 'का प्रयोग करें यदि आप स्टेटमेंट्स को
बकवास में कहते हैं

5
@Zoska टिप्पणी में जोड़ने के लिए, आपको पहले एक स्थान की आवश्यकता है [क्योंकि यह एक कमांड के रूप में कार्यान्वित किया जाता है, 'जो [] का प्रयास करें।
डैनियल दा कुन्हा

1
बेहतर उदाहरण नीचे दिए गए लिंक पर दिया गया है: stackoverflow.com/questions/4341630/…
रामकृष्ण

3
@ बरमेर निश्चित रूप से यह नामकरण तब testतक ठीक है जब तक कि यह पथ पर नहीं है?
525

जवाबों:


1098

किसी भी अन्य साधारण कमांड की तरह, [ ... ]या testइसके तर्कों के बीच रिक्त स्थान की आवश्यकता होती है।

if [ "$#" -ne 1 ]; then
    echo "Illegal number of parameters"
fi

या

if test "$#" -ne 1; then
    echo "Illegal number of parameters"
fi

सुझाव

बैश में होने पर, [[ ]]इसके बजाय का उपयोग करना पसंद करें क्योंकि यह शब्द विभाजन और अपने वैरिएबल के लिए मार्गनिर्देशन का विस्तार नहीं करता है कि जब तक यह अभिव्यक्ति का हिस्सा नहीं होता तब तक उद्धृत करना आवश्यक नहीं हो सकता है।

[[ $# -ne 1 ]]

इसमें कुछ अन्य विशेषताएं भी हैं जैसे कि अनक्वॉटेड कंडीशन ग्रुपिंग, पैटर्न मैचिंग (विस्तारित पैटर्न से मेल खाते हुए extglob) और रेगेक्स मिलान।

निम्न उदाहरण जाँचता है कि क्या तर्क मान्य हैं। यह एक या दो तर्क देता है।

[[ ($# -eq 1 || ($# -eq 2 && $2 == <glob pattern>)) && $1 =~ <regex pattern> ]]

शुद्ध गणित भाव के लिए, का उपयोग कर (( ))कुछ करने के लिए अभी भी बेहतर हो सकता है, लेकिन वे अभी भी संभव हो रहे हैं [[ ]]चाहते अपने अंकगणितीय ऑपरेटर के साथ -eq, -ne, -lt, -le, -gt, या -geएक भी स्ट्रिंग तर्क के रूप में अभिव्यक्ति रखकर:

A=1
[[ 'A + 1' -eq 2 ]] && echo true  ## Prints true.

यदि आपको इसे अन्य सुविधाओं के साथ संयोजित करने की आवश्यकता होगी तो यह सहायक होना चाहिए [[ ]]

स्क्रिप्ट से बाहर निकलना

जब अवैध पैरामीटर को पास कर दिया जाता है तो स्क्रिप्ट से बाहर निकलना भी तर्कसंगत है। यह पहले से ही इवांका द्वारा टिप्पणियों में सुझाया गया है, लेकिन किसी ने इस उत्तर को संपादित किया है ताकि इसे लौटाए गए मूल्य के साथ हो, इसलिए मैं इसे सही कर सकता हूं।-1

-1हालांकि बैश द्वारा एक तर्क के रूप में स्वीकार किया जाना exitस्पष्ट रूप से प्रलेखित नहीं है और एक सामान्य सुझाव के रूप में उपयोग किए जाने के लिए सही नहीं है। 64इसके sysexits.hसाथ परिभाषित होने के बाद भी सबसे औपचारिक मूल्य है #define EX_USAGE 64 /* command line usage error */। अधिकांश उपकरण जैसे अमान्य तर्कों पर lsभी लौटते हैं 2। मैं 2अपनी स्क्रिप्ट में भी लौटता था, लेकिन हाल ही में मुझे वास्तव में परवाह नहीं थी, और बस 1सभी त्रुटियों में उपयोग किया गया था। लेकिन चलो बस 2यहाँ जगह है क्योंकि यह सबसे आम है और शायद ओएस-विशिष्ट नहीं है।

if [[ $# -ne 1 ]]; then
    echo "Illegal number of parameters"
    exit 2
fi

संदर्भ


2
ओपी: ध्यान रखें कि [सिर्फ एक और कमांड है, यानी, कोशिश करें which [
सिंह

5
@ लियो कमांड का निर्माण किया जा सकता है, और नहीं किया जा सकता है। बैश में, [एक बिलिन है, जबकि [[एक कीवर्ड है। कुछ पुराने गोले में, [बिलियन भी नहीं है। आदेश की तरह [सबसे प्रणालियों में एक बाहरी कमांड के रूप में स्वाभाविक रूप से सह-अस्तित्व, लेकिन आंतरिक आदेशों के साथ बाईपास जब तक आप खोल द्वारा प्राथमिकता के आधार पर कर रहे हैं commandया exec। शेल के प्रलेखन की जांच करें कि वे कैसे मूल्यांकन करते हैं। उनके अंतर पर ध्यान दें, और वे हर शेल में अलग तरह से कैसे व्यवहार कर सकते हैं।
konsolebox

77

यदि आप संख्याओं के साथ काम कर रहे हैं तो अंकगणितीय अभिव्यक्तियों का उपयोग करना एक अच्छा विचार हो सकता है ।

if (( $# != 1 )); then
    echo "Illegal number of parameters"
fi

वर्तमान मामले में यह एक अच्छा विचार क्यों हो सकता है? दक्षता, पोर्टेबिलिटी और अन्य मुद्दों को ध्यान में रखते हुए, सबसे सरल और सबसे सार्वभौमिक रूप से समझे गए सिंटैक्स का उपयोग करना सबसे अच्छा नहीं है, अर्थात [ ... ], जब यह काम ठीक है और कोई फैंसी ऑपरेशन की आवश्यकता नहीं है?
अधिकतम

@ मोम अंकगणितीय विस्तार $(( ))फैंसी नहीं हैं और सभी पोसिक्स गोले द्वारा कार्यान्वित किए जाने चाहिए। हालाँकि, (( ))सिंटैक्स (बिना $) इसका हिस्सा नहीं है। यदि आप किसी कारण से सीमित हैं, तो आप निश्चित रूप से [ ]इसके बजाय उपयोग कर सकते हैं , लेकिन ध्यान रखें कि तब आपको [[ ]]भी उपयोग नहीं करना चाहिए । मुझे आशा है कि आप [ ]इन विशेषताओं के कारणों को समझते हैं और इन कारणों से मौजूद हैं। लेकिन यह एक बैश सवाल था, इसलिए हम बैश जवाब दे रहे हैं ( "अंगूठे के एक नियम के रूप में, [] का उपयोग चिह्नों और फाइलों के लिए किया जाता है। यदि आप संख्याओं की तुलना करना चाहते हैं, तो एक अंकगणितीय एक्सप्रेशन" का उपयोग करें
एलेक्स-डैनियल जकीमेंको-ए।

39

[]:! =!, =, == ... स्ट्रिंग तुलना संचालक हैं और -eq; -gt ... अंकगणितीय द्विआधारी हैं।

मै इस्तेमाल करूंगा:

if [ "$#" != "1" ]; then

या:

if [ $# -eq 1 ]; then

9
==वास्तव में एक गैर-दस्तावेजी सुविधा है, जो होता है जीएनयू के साथ काम करने test। यह FreeBSD के साथ काम करने के लिए भी होता है test, लेकिन यह फू पर काम नहीं कर सकता हैtestकेवल मानक तुलना है =(बस FYI करें)।
मार्टिन टूरनोइज

1
इसे बैश मैन एंट्री पर प्रलेखित किया जाता है: जब == और! = ऑपरेटरों का उपयोग किया जाता है, ऑपरेटर के दाईं ओर स्ट्रिंग को एक पैटर्न माना जाता है और पैटर्न मिलान के तहत नीचे वर्णित नियमों के अनुसार मिलान किया जाता है। यदि शेल विकल्प nocasematch सक्षम है, तो मैच अक्षर वर्णों के मामले की परवाह किए बिना किया जाता है। वापसी मान 0 है यदि स्ट्रिंग मिलान (==) या पैटर्न से मेल नहीं खाता है (=!) और 1 अन्यथा। पैटर्न के किसी भी हिस्से को स्ट्रिंग के रूप में मिलान करने के लिए मजबूर करने के लिए उद्धृत किया जा सकता है।
झ्वारस

2
@ झावर: कारपेटस्मोकर ने ठीक यही कहा है: यह कुछ कार्यान्वयन में काम कर सकता है (और वास्तव में, यह बाश में काम करता है), लेकिन यह पॉसिक्स-अनुरूप नहीं है । उदाहरण के लिए, यह होगा असफल साथ dash: dash -c '[ 1 == 1 ]'। POSIX केवल निर्दिष्ट करता है =, और नहीं ==
gnourf_gniourf

34

यदि आप केवल एक विशेष तर्क याद कर रहे हैं, तो बेलिंग में रुचि रखते हैं, पैरामीटर प्रतिस्थापन महान है:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

यह बशर्ते के साथ भरी हुई नहीं है?
ड्वाइट स्पेंसर

@DwightSpencer क्या यह मायने रखेगा?
konsolebox

@Temak I यदि आपके पास विशिष्ट प्रश्न हैं, लेकिन लिंक्ड-इन लेख मुझे समझाता है कि यह बेहतर है।
पैट

13

एक सरल एक लाइनर जो काम करता है उसका उपयोग किया जा सकता है:

[ "$#" -ne 1 ] && ( usage && exit 1 ) || main

यह टूट जाता है:

  1. मापदंडों के आकार के लिए बैश चर का परीक्षण करें $ 1 नहीं 1 (उप कमांड की हमारी संख्या) के बराबर
  2. यदि सही है तो कॉल उपयोग () फ़ंक्शन और स्थिति 1 के साथ बाहर निकलें
  3. अन्य कॉल मुख्य () फ़ंक्शन

नोट करने के लिए सोचता है:

  • उपयोग () सिर्फ सरल गूंज हो सकता है "$ 0: params"
  • मुख्य एक लंबी स्क्रिप्ट हो सकती है

1
यदि आपके पास उस लाइन के बाद लाइनों का एक और सेट है, तो यह गलत exit 1होगा क्योंकि केवल उप-संदर्भ के संदर्भ में लागू होगा जो इसे केवल इसका पर्याय बना देगा ( usage; false )। जब विकल्प-पार्सिंग की बात आती है तो मैं सरलीकरण के उस तरीके का प्रशंसक नहीं हूं, लेकिन आप { usage && exit 1; }इसके बजाय उपयोग कर सकते हैं । या शायद बस { usage; exit 1; }
konsolebox

1
@konsolebox (उपयोग और& से बाहर निकलें 1) ksh, zsh और bash 2.0 को वापस करने के लिए काम करता है। {...} सिंटैक्स केवल हाल ही में 4.0+ बैश का है। मुझे गलत मत समझिए अगर कोई एक तरीका आपके लिए ठीक काम करता है तो उसका उपयोग करें लेकिन याद रखें कि हर कोई बैश के समान कार्यान्वयन का उपयोग नहीं करता है जो आप करते हैं और हमें पॉज़िक्स मानकों को कोड करना चाहिए न कि बशीज़।
ड्वाइट स्पेंसर

मुझे यकीन नहीं है कि आप क्या कह रहे हैं। {...}एक सामान्य वाक्यविन्यास है और यह सभी के लिए उपलब्ध है यदि सभी गोले आधारित नहीं हैं sh, यहां तक ​​कि उन पुराने गोले भी जो POSIX मानकों का पालन नहीं करते हैं।
konsolebox

7

इस बैश चीटशीट की जाँच करें , यह बहुत मदद कर सकता है।

में पारित तर्कों की लंबाई की जांच करने के लिए, आप उपयोग करते हैं "$#"

में पारित तर्कों की सरणी का उपयोग करने के लिए, आप उपयोग करते हैं "$@"

लंबाई की जाँच, और पुनरावृत्ति का एक उदाहरण होगा:

myFunc() {
  if [[ "$#" -gt 0 ]]; then
    for arg in "$@"; do
      echo $arg
    done
  fi
}

myFunc "$@"

इस मुखर ने मेरी मदद की, लेकिन मेरे और मेरी स्थिति के लिए कुछ चीजें याद आ रही थीं। उम्मीद है कि यह किसी की मदद करता है।


0

यदि आप सुरक्षित पक्ष में रहना चाहते हैं, तो मैं गेटटॉप का उपयोग करने की सलाह देता हूं।

यहाँ एक छोटा सा उदाहरण है:

    while getopts "x:c" opt; do
      case $opt in
        c)
          echo "-$opt was triggered, deploy to ci account" >&2
          DEPLOY_CI_ACCT="true"
          ;;
            x)
              echo "-$opt was triggered, Parameter: $OPTARG" >&2 
              CMD_TO_EXEC=${OPTARG}
              ;;
            \?)
              echo "Invalid option: -$OPTARG" >&2 
              Usage
              exit 1
              ;;
            :)
              echo "Option -$OPTARG requires an argument." >&2 
              Usage
              exit 1
              ;;
          esac
        done

अधिक जानकारी के लिए यहाँ देखें उदाहरण के लिए http://wiki.bash-hackers.org/howto/getopts_tutorial


0

यहां केवल एक पैरामीटर की जांच करने के लिए एक सरल एक लाइनर दिया गया है अन्यथा स्क्रिप्ट से बाहर निकलें:

[ "$#" -ne 1 ] && echo "USAGE $0 <PARAMETER>" && exit

-1

आपको परीक्षण की स्थिति के बीच रिक्त स्थान जोड़ना चाहिए:

if [ $# -ne 1 ]; 
    then echo "illegal number of parameters"
fi

आशा है कि ये आपकी मदद करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.