अगर स्थिति के आधार पर केस गिरता है


11

मैं एक रास्ता खोज रहा हूँ, जो कि bash में केस की स्थिति के भीतर if if पर आधारित है। उदाहरण के लिए:

input="foo"
VAR="1"

case $input in
foo)
    if [ $VAR = "1" ]; then

        # perform fallthrough

    else

        # do not perform fallthrough

    fi
;;
*)
    echo "fallthrough worked!"
;;
esac

उपरोक्त कोड में, यदि वैरिएबल VARहै 1, तो मैं चाहूंगा कि केस की स्थिति में गिरावट आए।


1
छोटा सवाल: क्या आप if [ $VAR -eq 1 ]; thenजो कुछ भी है उसमें कोड के हिस्से से कूदने की कोशिश कर रहे हैं *)? क्योंकि यह किस तरह से परती अवस्था से अलग है, इस प्रकार आपके प्रश्न को थोड़ा भ्रामक बना देता है।
सर्गी कोलोडियाज़नी

जवाबों:


8

आप नहीं कर सकते। के caseमाध्यम से गिरने का तरीका ;;विभाजक को ;&(या ;;&) से बदलना है । और यह एक सिंटैक्स त्रुटि है कि अगर एक के अंदर डाल दिया।

आप पूरे तर्क को नियमित सशर्त के रूप में लिख सकते हैं:

if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
    one branch ...
else   # $input = "foo" && $VAR != 1
    another branch...
fi


@Isaac, ठीक है, हाँ, हालांकि वे एक पर गिरावट का आधार निर्दिष्ट किया था if
इलकाचु

+1 करने के लिए स्पष्ट: मैंने आपका जवाब दिया। :)।
इसहाक

7

मैं आपके तर्क को पुनर्गठन करने का सुझाव दूंगा: "फालतू" कोड को एक फंक्शन में डाल दें:

fallthrough() { echo 'fallthrough worked!'; }

for input in foo bar; do
    for var in 1 2; do
        echo "$input $var"
        case $input in
            foo)
                if (( var == 1 )); then
                    echo "falling through"
                    fallthrough
                else
                    echo "not falling through"
                fi
            ;;
            *) fallthrough;;
        esac
    done
done

आउटपुट

foo 1
falling through
fallthrough worked!
foo 2
not falling through
bar 1
fallthrough worked!
bar 2
fallthrough worked!

7

निम्न स्क्रिप्ट अपने परीक्षण "अंदर बाहर" इस अर्थ में कि हम परीक्षण में बदल जाता है $varऔर फिर fallthrough प्रदर्शन (का उपयोग कर ;&एक में case) के आधार पर $input

हम ऐसा करते हैं क्योंकि या नहीं, के सवाल "fallthrough प्रदर्शन" वास्तव में केवल पर निर्भर है $input, तो $varहै 1। यदि यह कोई अन्य मूल्य है, तो सवाल यह है कि क्या गिरावट को करने के लिए भी नहीं पूछा जाना चाहिए।

#/bin/bash

input='foo'
var='1'

case $var in
    1)
        case $input in
            foo)
                echo 'perform fallthrough'
                ;&
            *)
                echo 'fallthough worked'
        esac
        ;;
    *)
        echo 'what fallthrough?'
esac

या, बिना case:

if [ "$var" -eq 1 ]; then
    if [ "$input" = 'foo' ]; then
        echo 'perform fallthrough'
    fi
    echo 'fallthough worked'
else
    echo 'what fallthrough?'
fi

मुझे लगता है कि ओपी आपको वास्तव में क्या चाहिए था, जो कि उनके मूल से कूदता हुआ प्रतीत होता है, जो कुछ भी बयान करता है *)। पहले से ही मेरा +1 है।
सर्गी कोलोडियाज़नी

5

ऐसा कुछ नहीं जो मैं करूंगा, लेकिन आप कुछ हासिल कर सकते हैं:

shopt -s extglob # for !(*)
default='*'
case $input in
  (foo)
    if [ "$VAR" = 1 ]; then
      echo going for fallthrough
    else
      echo disabling fallthrough
      default='!(*)'
    fi ;;&

  ($default)
    echo fallthrough
esac

2

एक साथ दोनों चर का परीक्षण करें (4.0-अल्फा + को बैश करें):

#!/bin/bash
while (($#>1)); do
    input=$1    VAR=$2
    echo "input=${input} VAR=${VAR}"; shift 2

    if [ "$VAR" = 1 ]; then new=1; else new=0; fi

    case $input$new in
    foo0)   echo "do not perform fallthrough"   ;;
    foo*)   echo "perform fallthrough"          ;&
    *)      echo "fallthrough worked!"          ;;
    esac

    echo
done

परीक्षण पर:

$ ./script foo 0   foo 1   bar baz
input=foo VAR=0
do not perform fallthrough

input=foo VAR=1
perform fallthrough
fallthrough worked!

input=bar VAR=baz
fallthrough worked!

साफ और सरल।

यह समझें कि परीक्षण किए गए मान ( $new) में केवल दो संभावित मान होने चाहिए, यही कारण है कि यदि खंड है, तो VAR को एक बूलियन मान में बदलने के लिए। यदि VAR को बूलियन बनाया जा सकता है, तो 0( और 1) को caseहटाने और हटाने के लिए परीक्षण करें if


1

आप फालतू को डिफ़ॉल्ट बना सकते हैं लेकिन एक शर्त रखें कि कोड केवल तभी निष्पादित होता है जब शर्त पूरी हो जाती है

#!/bin/bash

input='foo'
var='1'

case $input in
foo)
        echo "Do fall through"
;& #always fall through
*)
        if [ $var = "1" ] #execute only if condition matches
        then
        echo "fallthrough took place"
        fi
esac

लेकिन जैसा कि ilkkachu ने सुझाव दिया था कि आप स्विच के बजाय शर्तों का भी उपयोग कर सकते हैं।


1

यदि आपको किसी के बारे में शिकायत नहीं है, तो वे आपके कोड को नहीं समझते हैं, आप बस दो शर्तों के क्रम को बदल सकते हैं:

input="foo"
VAR="1"

if 
    case $input in
    foo)
        [ $VAR = "1" ]
    ;;
    esac
then
    echo "fallthrough worked!"
fi

या:

input="foo"
VAR="1"

case $input in
foo)
    [ $VAR = "1" ]
;;
esac &&
    echo "fallthrough worked!"

सरल और स्पष्ट (कम से कम मेरे लिए)। caseखुद को समर्थन का समर्थन नहीं करता है। लेकिन आप इसे अन्य शाखाओं के रिटर्न मान के संबंध में बदलने *)के &&बाद बदल सकते esacहैं।


-4

नए ;&और ;;&ऑपरेटरों को 4.0 में पेश कियाBash गया था और हालांकि वे दोनों समान परिस्थितियों में उपयोगी हो सकते हैं, मुझे लगता है कि वे आपके मामले में किसी काम के नहीं हैं। यह man bashइन ऑपरेटरों के बारे में क्या कहता है:

यदि ;; ऑपरेटर का उपयोग किया जाता है, पहले पैटर्न के मैच के बाद किसी भी बाद के मैचों का प्रयास नहीं किया जाता है। का उपयोग कर; & के स्थान पर ;; पैटर्न के अगले सेट से जुड़ी सूची को जारी रखने के लिए निष्पादन का कारण बनता है। का उपयोग ;; & के स्थान पर ;; शेल के बयान में अगले पैटर्न सूची का परीक्षण करने का कारण बनता है, यदि कोई हो, और एक सफल मैच पर किसी भी संबंधित सूची को निष्पादित करता है।

दूसरे शब्दों में, ;&के माध्यम से गिरावट है और जैसा कि हम इसे से पता Cऔर ;;&बनाता है bashशेष मामलों के बजाय से लौटने की जांच caseपूरी तरह से ब्लॉक। आप ;;&यहां कार्रवाई का एक अच्छा उदाहरण पा सकते हैं : /programming//a/24544780/3691891

ऐसा कहा जा रहा है, न तो आपकी स्क्रिप्ट में इस्तेमाल किया जा सकता है ;&और न ही ;;&क्योंकि दोनों ही उस पर चले *)जाएंगे।

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

#!/usr/bin/env bash

function jumpto
{
    label=$1
    cmd=$(sed -n "/$label:/{:a;n;p;ba};" "$0" | grep -v ':$')
    cmd=$(echo "$cmd" | sed 's,;;,,')
    cmd=$(echo "$cmd" | sed 's,esac,,')
    eval "$cmd"
}

input="foo"
VAR="1"

case $input in
foo)
    if [ $VAR = "1" ]; then

        printf "perform fallthrough\n"
        jumpto ft
    else
        printf "do not perform fallthrough\n"

    fi
;;
*)
    ft:
    echo "fallthrough worked!"
;;
esac

क्यों एक डाउनवोट?
अर्कादिअस ड्राज्स्की

1
यह एक खिलौना उदाहरण में काम कर सकता है लेकिन यह लगभग-समझ से बाहर है और एक बड़ी स्क्रिप्ट में काम नहीं करेगा। जिस तरह से आपने गोटो का अनुकरण किया है वह बेहद नाजुक है, और यह कहना कि यह वास्तव में गोटो का अनुकरण करता है एक अतिशयोक्ति है। कोड jumptoफ़ंक्शन से लौटता है और इसके बाद जो भी आता है उसे निष्पादित करता है। यह तथ्य कि यह बीच के ब्लॉक के बाद निरंतर निष्पादन के बराबर है ft:और ;;यह एक संयोग है क्योंकि jumptoजम्प-टू-ब्लॉक के रूप में एक ही जटिल कमांड में अंतिम कमांड है।
गिल्स एसओ- बुराई को रोकना '28

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