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


67

मैं एक स्क्रिप्ट लिखने की कोशिश कर रहा हूं, जहां मैं जांचना चाहता हूं कि क्या कोई भी पैरामीटर एक बैश स्क्रिप्ट को पास करने के लिए स्ट्रिंग से मेल खाता है। जिस तरह से मैंने इसे अभी सेटअप किया है

if [ "$3" != "-disCopperBld" -a "$4" != "-disCopperBld" -a "$5" != "-disCopperBld" -a "$6" != "-disCopperBld"]

लेकिन बड़ी संख्या में पैरामीटर हो सकते हैं, इसलिए मैं सोच रहा था कि क्या ऐसा करने का कोई बेहतर तरीका है?

धन्यवाद

संपादित करें: मैंने कोड का यह हिस्सा बाहर की कोशिश की, और विकल्प के साथ स्क्रिप्ट को बुलाया, -DisableVenusBld, लेकिन यह अभी भी "स्टार्ट बिल्ड का निर्माण" करता है। क्या मुझसे कुछ ग़लत हो रहा है? अग्रिम में धन्यवाद!

while [ $# -ne 0 ]
do
    arg="$1"
    case "$arg" in
        -disableVenusBld)
            disableVenusBld=true
            ;;
        -disableCopperBld)
            disableCopperBld=true
            ;;
        -disableTest)
            disableTest=true
            ;;
        -disableUpdate)
            disableUpdate=true
            ;;
        *)
            nothing="true"
            ;;
    esac
    shift
done

if [ "$disableVenusBld" != true ]; then
    echo "Starting build"
fi

उत्तर दोस्तों के लिए धन्यवाद, मैं सराहना करता हूं कि मेरी मदद करने के लिए समय निकाल लेंगे। मैंने कोड का एक हिस्सा बनाने की कोशिश की, लेकिन मुझे यह पता नहीं लग सकता है कि क्या गलत हो रहा है। कोई विचार? (मैंने अपने मूल पोस्ट के संपादन में कोड पेस्ट किया है)
iman453

हम्म: यह मेरे लिए काम करता है। मैंने #! /bin/sh -वहाँ जो आपने शामिल किया है उसके शीर्ष पर जोड़ा , स्क्रिप्ट को निष्पादन योग्य बना दिया, फिर ./t.sh"स्टार्ट बिल्ड" ./t.sh -disableVenusBldप्रिंट करता है , लेकिन कुछ भी प्रिंट नहीं करता है।
नॉर्मन ग्रे

जवाबों:


59

ऐसा लगता है कि आप शेल स्क्रिप्ट में ऑप्शन हैंडलिंग कर रहे हैं। यहाँ उस के लिए मुहावरा है:

#! /bin/sh -

# idiomatic parameter and option handling in sh
while test $# -gt 0
do
    case "$1" in
        --opt1) echo "option 1"
            ;;
        --opt2) echo "option 2"
            ;;
        --*) echo "bad option $1"
            ;;
        *) echo "argument $1"
            ;;
    esac
    shift
done

exit 0

(इंडेंट करने के लिए कुछ सम्मेलन होते हैं ;;, और कुछ गोले आपको विकल्प देने की अनुमति देते हैं (--opt1), जैसे ब्रेस मिलान के साथ मदद करने के लिए, लेकिन यह मूल विचार है)


3
एक shiftकथन का उपयोग तब किया जाता है जब एक कमांड के तर्कों की संख्या पहले से ज्ञात नहीं होती है, उदाहरण के लिए जब उपयोगकर्ता जितनी चाहें उतने तर्क दे सकते हैं। ऐसे मामलों में, तर्कों को एक whileलूप में संसाधित किया जाता है जिसकी परीक्षण स्थिति होती है $#। यह स्थिति तब तक सही है जब तक कि तर्कों की संख्या शून्य से अधिक है। $1चर और shiftबयान प्रक्रिया प्रत्येक तर्क। तर्कों की संख्या हर बार कम shiftहो जाती है और निष्पादित हो जाती है और अंततः शून्य हो जाती है, जिस पर whileलूप निकल जाता है। स्रोत
सर्ज स्ट्रोबोबांट

यहां अतिरिक्त echo $1 | sedतर्क मूल्य प्रसंस्करण के साथ एक समान उदाहरण है ।
सर्ज स्ट्रोबोबांट

26

इसने मेरे लिए काम किया। यह वही करता है जो आपने पूछा था और कुछ भी नहीं (कोई विकल्प नहीं प्रसंस्करण)। चाहे वह अच्छा हो या बुरा पोस्टर के लिए एक व्यायाम है :)

if [[ "$*" == *YOURSTRING* ]]
then
    echo "YES"
else
    echo "NO"
fi

यह $* सुपर-टेस्ट [[... ]]कोष्ठक की विशेष हैंडलिंग का लाभ उठाता है ।


2
IMHO के लिए यह सबसे सही उत्तर होना चाहिए, क्योंकि प्रश्न के लिए केवल एक पैरामीटर की उपस्थिति की जांच करना आवश्यक है। मैंने संपादित किया है, हालांकि, के लिए बदल रहा $*है $@, के बाद से परीक्षण स्ट्रिंग के लिए रिक्त स्थान हो सकता है और इसके बारे में bash के प्रलेखन के लिए लिंक जोड़ा गया है।
12

9
क्या आपका मतलब = ~ ऑपरेटर का उपयोग करना था? अन्यथा मैं नहीं देखता कि यह क्यों काम करना चाहिए, और वास्तव में जब मैं सटीक स्क्रिप्ट की कोशिश करता हूं तो यह काम नहीं करता है।
सेप्पो एनरवी जूल

3
काम नहीं कर रहा। bash -c 'echo args=$*; [[ "$@" == "bar" ]] && echo YES || echo NO' -- foo bar
टोबिया

2
यह संपूर्ण तर्क सूची की तुलना करता है your string। मुझे लगता है कि आपको वह करने की आवश्यकता है जो इस उत्तर द्वारा सुझाई गई है । यानी: bash -c 'echo args=$*; for i in "$@" ; do [[ $i == "bar" ]] && echo "Is set!" && break ; done' -- bar fooकाम करेगा।
स्टारफ्री

2
यह उत्तर पिछले चार वर्षों से गलत है क्योंकि h7r के संपादन ने इसे तोड़ दिया। मूल उत्तर (जो मैंने अब बहाल कर दिया है) काम करता है, बशर्ते कि "आपके तार" में कोई ग्लोब वर्ण न हो और कुछ गलत सकारात्मकता के साथ हो। उदाहरण के लिए, यदि कमांड है create a new certificateऔर "आपका स्ट्रिंग" है cat, तो यह मैच की रिपोर्ट करेगा क्योंकि certificate इसमें शामिल है cat
स्कॉट

8

कैसे (वाइल्डकार्ड के साथ) खोज के बारे में पूरे पैरामीटर स्थान:

if [[ $@ == *'-disableVenusBld'* ]]
then

संपादित करें: ठीक है, ठीक है, इसलिए यह एक लोकप्रिय जवाब नहीं था। कैसे इस बारे में, यह सही है!

if [[ "${@#-disableVenusBld}" = "$@" ]]
then
    echo "Did not find disableVenusBld"
else
    echo "Found disableVenusBld"
fi

Edit2: ठीक है, ठीक है, शायद यह सही नहीं है ... सोचें कि यह तभी काम करता है जब -परम सूची के प्रारंभ में हो और -paramXZY या -paramABC से भी मेल खाएगा। मुझे अभी भी लगता है कि मूल समस्या को बहुत अच्छी तरह से बैश स्ट्रिंग हेरफेर के साथ हल किया जा सकता है, लेकिन मैंने इसे यहाँ नहीं फटा है ... -नहीं ??


आपका दूसरा सुझाव - फ़िल्टरिंग प्रतिस्थापन को पूर्ण प्रतिस्थापन की तुलना करना - यथोचित रूप से अच्छी तरह से काम करता है, और तर्कों की सूची को बाधित नहीं करने का लाभ है।
डोना फेलो

क्या आप बता सकते हैं कि दूसरा सुझाव (विशेषकर ${@#) क्या करता है?
velop

1
@ उल्टा ज़रूर! तो आप जानते हैं कि $@एक विशेष चर है जो कमांड लाइन के सभी तर्क रखता है? अच्छी तरह से मैंने बस "-disableVenusBld" विकल्प को हटाने के लिए उस चर पर बैश स्ट्रिंग हेरफेर का उपयोग किया है, और फिर मैं इसे मूल से तुलना करता हूं $@। तो अगर $@बराबरी होती है -foo -barतो फिर ${@#-disableVenusBld}भी होगी -foo -bar, इसलिए मैं देख सकता हूं कि मैं जिस ध्वज की तलाश कर रहा हूं वह मौजूद नहीं है। हालांकि, अगर $@बराबर होती है -foo -disableVenusBld -barतो ${@#-disableVenusBld}हो सकता है -foo -barजो के बराबर नहीं है $@, इस प्रकार मुझे बता कि झंडा मैं तलाश कर रहा हूँ मौजूद है! शांत एह!
रिच

@ उल्लिखित यहां बैश स्ट्रिंग हेरफेर के बारे में और जानें: tldp.org/LDP/abs/html/string-manipulation.html
रिच

@ बहुत साफ ^ ^, स्पष्टीकरण के लिए thx।
velop

4
disCopperBld=
for x; do
  if [ "$x" = "-disCopperBld" ]; then disCopperBld=1; break; fi
done
if [ -n "$disCopperBld" ]; then
  ...
fi

यदि आपको केवल शुरू होने वाले मापदंडों का परीक्षण करने की आवश्यकता है $3, तो एक फ़ंक्शन में खोज करें:

## Usage: search_trailing_parameters NEEDLE NUM "$@"
## Search NEEDLE amongst the parameters, skipping $1 through ${$NUM}.
search_trailing_parameters () {
  needle=$1
  shift $(($2 + 2))
  for x; do
    if [ "$x" = "$needle" ]; then return 0; fi
  done
  return 1
}
if search_trailing_parameters -disCopperBld 2 "$@"; then
  ...
fi

लेकिन मुझे आश्चर्य है कि आप पहली बार में ऐसा करने की कोशिश क्यों कर रहे हैं, यह कोई आम जरूरत नहीं है। आमतौर पर, आप क्रम में विकल्पों को संसाधित करेंगे , जैसा कि आपके पिछले प्रश्न के डेनिस के उत्तर में है

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