बैश स्क्रिप्ट त्रुटि [:! =: Unary ऑपरेटर अपेक्षित है


95

मेरी स्क्रिप्ट में मैं यह जांचने में त्रुटि कर रहा हूं कि क्या पहला और एकमात्र तर्क -v के बराबर है, लेकिन यह एक वैकल्पिक तर्क है। मैं एक if स्टेटमेंट का उपयोग करता हूं लेकिन मुझे unary ऑपरेटर अपेक्षित त्रुटि मिलती रहती है।

यह कोड है:

if [ $1 != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

संपादित करें:

मुझे और अधिक विशिष्ट होना चाहिए: ऊपर की स्क्रिप्ट का यह भाग एक वैकल्पिक तर्क की जाँच कर रहा है और उसके बाद, यदि तर्क में प्रवेश नहीं किया गया है, तो इसे बाकी कार्यक्रम चलाना चाहिए।

#!/bin/bash

if [ "$#" -gt "1" ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" = -v ]; then
   echo "`ps -ef | grep -v '\['`"
else
   echo "`ps -ef | grep '\[' | grep root`"
fi

... वैसे, मुझे लगता है कि आप चाहते हैं echo "usage: $0 [-v]"; $-सक्रिय शेल विकल्प झंडे दिखाता है, वर्तमान स्क्रिप्ट का नाम नहीं।
चार्ल्स डफी

मेरे पास वह हिस्सा सही है, मैं चाहता हूं कि वह वर्तमान स्क्रिप्ट का नाम दिखाए।
user3380240

4
Stackoverflow में, और विशेष रूप से bash टैग में आपका स्वागत है! की जाँच करें टैग विकी , उपयोगी उपकरणों और संसाधनों के लिए की तरह shellcheck जो बाहर इस तरह कई मुद्दों इंगित करेगा (हालांकि हमेशा की व्याख्या नहीं)।
वह दूसरा लड़का

@ user3380240, $-है नहीं वर्तमान स्क्रिप्ट का नाम है। $0है।
चार्ल्स डफी

क्षमा करें, यह एक टाइपो था।
user3380240

जवाबों:


186

उल्लेख। उद्धरण!

if [ "$1" != -v ]; then

अन्यथा, जब $1पूरी तरह से खाली हो जाता है, तो आपका परीक्षण बन जाता है:

[ != -v ]

के बजाय

[ "" != -v ]

... और !=एक एकरी संचालक नहीं है (जो कि केवल एक तर्क लेने में सक्षम है)।


8
या, यदि आप पोर्टेबिलिटी के बारे में चिंतित नहीं हैं, तो आप डबल ब्रैकेट का उपयोग कर सकते हैं, जिसके अंदर चर विस्तार की आवश्यकता नहीं है: if [[ $1 != -v ]]; then
माइक होल

@MikeHolt, वास्तव में - मैं इस सवाल पर एक टिप्पणी में ऊपर लाता हूं।
चार्ल्स डफी

@DanielDinnyes, यदि IFS=1, तो फिर [ $# -eq 1 ]इतना अच्छा व्यवहार नहीं करेगा, जबकि [ "$#" -eq 1 ]तब भी जैसा व्यवहार होता है । यह एक पैथोलॉजिकल केस है, निश्चित रूप से, लेकिन सॉफ्टवेयर को लिखने के लिए बेहतर है जो पसंद को देखते हुए उन्हें नहीं है।
चार्ल्स डफी

-2

या जो बड़े पैमाने पर भारी लगता है, लेकिन वास्तव में सरलीकृत है ... बहुत सारे आपके सभी मामलों को कवर करता है, और कोई खाली स्ट्रिंग या एकतरफा चिंता नहीं है।

मामले में पहला आर्ग '-v' है, फिर अपनी स्थिति को ठीक करें ps -ef, अन्यथा अन्य सभी मामलों में उपयोग को फेंक दें।

#!/bin/sh
case $1 in
  '-v') if [ "$1" = -v ]; then
         echo "`ps -ef | grep -v '\['`"
        else
         echo "`ps -ef | grep '\[' | grep root`"
        fi;;
     *) echo "usage: $0 [-v]"
        exit 1;; #It is good practice to throw a code, hence allowing $? check
esac

अगर कोई परवाह नहीं करता है कि '-v' arg कहाँ है, तो बस एक लूप के अंदर केस छोड़ें। यह सभी आर्गों को चलने और कहीं भी '-v' खोजने की अनुमति देगा (बशर्ते यह मौजूद हो)। इसका मतलब है कि कमांड लाइन तर्क आदेश महत्वपूर्ण नहीं है। प्रस्तुत किया जा सकता है, जैसा कि प्रस्तुत किया गया है, चर arg_match सेट है, इस प्रकार यह केवल एक ध्वज है। यह '-v' arg की कई घटनाओं के लिए अनुमति देता है। एक '-v' की अन्य सभी घटनाओं को आसानी से अनदेखा कर सकता है।

#!/bin/sh

usage ()
 {
  echo "usage: $0 [-v]"
  exit 1
 }

unset arg_match

for arg in $*
 do
  case $arg in
    '-v') if [ "$arg" = -v ]; then
           echo "`ps -ef | grep -v '\['`"
          else
           echo "`ps -ef | grep '\[' | grep root`"
          fi
          arg_match=1;; # this is set, but could increment.
       *) ;;
  esac
done

if [ ! $arg_match ]
 then
  usage
fi

लेकिन, एक तर्क की कई घटनाओं को अनुमति दें जैसे स्थितियों में उपयोग करने के लिए सुविधाजनक है:

$ adduser -u:sam -s -f -u:bob -trace -verbose

हम तर्कों के क्रम के बारे में परवाह नहीं करते हैं, और यहां तक ​​कि कई -u तर्कों की अनुमति देते हैं। हाँ, यह भी अनुमति देने के लिए एक सरल मामला है:

$ adduser -u sam -s -f -u bob -trace -verbose

$*इस संदर्भ में उपयोग नहीं किया जाना चाहिए: यह आइटम्स को स्ट्रिंग में विभाजित करता है जो स्ट्रिंग-स्प्लिट और ग्लोब-विस्तारित दोनों हैं; इसके विपरीत "$@", जो वस्तुओं को उनके सटीक मूल मूल्यों के साथ छोड़ देता है। और आप कुछ उद्धरण याद कर रहे हैं, जो shellcheck.net पकड़ लेगा (एक विकी पृष्ठ से जुड़े चेतावनियों के साथ जो बताता है कि वे उद्धरण महत्वपूर्ण क्यों थे)।
चार्ल्स डफी

एक ठोस उदाहरण के रूप में, विचार करें -U'Bob Barker'; एक अलग आइटम के रूप for arg in $*में -UBobऔर फिर इसे देखेंगे Barker; जबकि एक ही तार के रूप में for item in "$@"देखेंगे -UBob Barker
चार्ल्स डफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.