टर्नेरी ऑपरेटर (:) बैश में


442

क्या ऐसा कुछ करने का कोई तरीका है

int a = (b == 5) ? c : d;

बैश का उपयोग?


1
@ dutCh के उत्तर से पता चलता है कि bashइसमें "टर्नरी ऑपरेटर" के समान कुछ है लेकिन bashइसे "सशर्त ऑपरेटर" कहा जाता है expr?expr:expr( man bashगोटो सेक्शन "अंकगणितीय मूल्यांकन")। ध्यान रखें bash"सशर्त ऑपरेटर" मुश्किल है और इसके पास कुछ गोचर्स हैं।
ट्रेवर बॉयड स्मिथ

बैश में पूर्णांकों के लिए एक टर्नरी ऑपरेटर होता है और यह अंकगणितीय अभिव्यक्ति के अंदर काम करता है ((...))शैल अंकगणित देखें ।
कोडफोर्स

1
जैसा कि @codeforester ने उल्लेख किया है, टर्नेरी ऑपरेटर अंकगणितीय विस्तार $(( ))और अंकगणितीय मूल्यांकन के साथ काम करता है (( ))। यह भी देखें https://mywiki.wooledge.org/ArithmeticExpression
काई

जवाबों:


490

टर्नरी ऑपरेटर ? :का संक्षिप्त रूप हैif/else

case "$b" in
 5) a=$c ;;
 *) a=$d ;;
esac

या

 [[ $b = 5 ]] && a="$c" || a="$d"

103
ध्यान दें कि =ऑपरेटर स्ट्रिंग समानता के लिए परीक्षण करता है, न कि संख्यात्मक समानता (यानी [[ 05 = 5 ]]गलत है)। यदि आप संख्यात्मक तुलना चाहते हैं, तो -eqइसके बजाय का उपयोग करें ।
गॉर्डन डेविसन

10
यह छोटे फॉर्म के लिए अधिक हैif/then/else
vol7ron

15
यह एक शॉर्ट सर्किट व्यवहार का उपयोग करने के लिए एक सहायक ऑपरेटर प्रभाव प्राप्त करने का एक प्रतिभाशाली तरीका है :) :) :) :)
mtk

6
क्यों [[और]]? यह इस तरह से भी काम करता है: [$ b = 5] && a = "$ c" || a = "$ d"
kdubs

83
cond && op1 || op2निर्माण एक अंतर्निहित बग है: अगर op1किसी भी कारण से अशून्य बाहर निकलने का दर्जा प्राप्त है, परिणाम चुपचाप हो जाएगा op2if cond; then op1; else op2; fiएक पंक्ति भी है और इसमें वह दोष नहीं है।
ivan_pozdeev

375

कोड:

a=$([ "$b" == 5 ] && echo "$c" || echo "$d")

58
यह दूसरों की तुलना में बेहतर है ... तृतीयक ऑपरेटर के बारे में बात यह है कि यह एक ऑपरेटर है, इसलिए यह उचित संदर्भ एक अभिव्यक्ति में है, इसलिए इसे एक मूल्य वापस करना होगा।
निक फेरियर

2
यह सबसे संक्षिप्त तरीका है। इस बात का ध्यान रखें कि यदि वह भाग echo "$c"एक अलियास, मल्टी-लाइनेड कमांड (जैसे echo 1; echo 2) है, तो आपको इसे कोष्ठक में संलग्न करना चाहिए।
मैट

2
यह परीक्षण किए गए कमांड के किसी भी आउटपुट को भी कैप्चर करेगा, (हाँ, इस विशेष मामले में, हम "जानते हैं" यह कोई उत्पादन नहीं करता है)।
ivan_pozdeev

8
ऑपरेटरों की यह श्रृंखला केवल एक टर्नरी ऑपरेटर की तरह व्यवहार करती है यदि आप सकारात्मक हैं कि आदेश के बाद &&गैर-शून्य निकास स्थिति नहीं होगी। अन्यथा, a && b || c "अप्रत्याशित रूप से" चलेंगे cअगर aसफल होता है, लेकिन bविफल रहता है।
चेपनर

155

यदि कोई चर सेट कर रहा है, तो स्थिति केवल जाँच रही है, एक छोटा रूप भी है:

a=${VAR:-20}

करने के लिए आवंटित करेगा aका मूल्य VARअगर VAR, सेट किया गया है अन्यथा यह यह डिफ़ॉल्ट मान प्रदान करेंगे 20- यह भी एक अभिव्यक्ति का एक परिणाम हो सकता है।

टिप्पणी में एलेक्स के रूप में, इस दृष्टिकोण को तकनीकी रूप से "पैरामीटर विस्तार" कहा जाता है।


6
इसमें हाइफ़न के साथ एक स्ट्रिंग पैरामीटर पास करने के मामले में, मुझे उद्धरण चिह्नों का उपयोग करना था: a=${1:-'my-hyphenated-text'}
sranicole

1
आलसी के लिए लिंक - बस विकल्प से अतिरिक्त ऑपरेटर हैं ( :-)
जस्टिन व्रोबेल

10
@JustinWrobel - दुर्भाग्य से कोई वाक्यविन्यास नहीं है ${VAR:-yes:-no}
केन विलियम्स

76
if [ "$b" -eq 5 ]; then a="$c"; else a="$d"; fi

cond && op1 || op2अभिव्यक्ति अन्य उत्तर में सुझाव दिया एक अंतर्निहित बग है: अगर op1एक अशून्य बाहर निकलने का दर्जा प्राप्त है, op2चुपचाप परिणाम हो जाता है; त्रुटि भी -eमोड में नहीं पकड़ी जाएगी । तो, वह अभिव्यक्ति केवल उपयोग करने के लिए सुरक्षित है यदि op1कभी विफल नहीं हो सकती (जैसे, :)true अंतर्निहित, या किसी भी परिचालन (विभाजन और ओएस कॉल) की तरह है कि असफल हो सकता है बिना चर काम करते हैं)।

""उद्धरणों पर ध्यान दें । यदि $bरिक्त है या व्हाट्सएप है तो पहली जोड़ी एक वाक्यविन्यास त्रुटि को रोकेगी । अन्य सभी व्हाट्सएप के एकल स्थानों में अनुवाद को रोकेंगे।


1
मैंने पहले से भी देखा है, मेरा मानना ​​है कि [ "x$b" -eq "x" ]विशेष रूप से खाली स्ट्रिंग के लिए परीक्षण किया जाता है। मुझे zsh ('PARAMETER EXPANSION' द्वारा zshexpn manpage) में प्रयुक्त सिंटैक्स का उपयोग करना पसंद है, लेकिन मुझे उनकी पोर्टेबिलिटी के बारे में ज्यादा जानकारी नहीं है।
जॉन पी


46
(( a = b==5 ? c : d )) # string + numeric

31
यह संख्यात्मक तुलना और असाइनमेंट के लिए अच्छा है , लेकिन यह अप्रत्याशित परिणाम देगा यदि आप इसे स्ट्रिंग तुलना और असाइनमेंट के लिए उपयोग करते हैं .... (( ))किसी भी / सभी तार के रूप में व्यवहार करता है0
पीटर

3
यह भी लिखा जा सकता है:a=$(( b==5 ? c : d ))
joeytwiddle

33
[ $b == 5 ] && { a=$c; true; } || a=$d

यह भाग के निष्पादन से बच जाएगा || जब गलती से && के बीच कोड और || विफल रहता है।


यह अभी भी -eमोड में त्रुटि को नहीं पकड़ेगा : (set -o errexit; [ 5 == 5 ] && { false; true; echo "success"; } || echo "failure"; echo $?; echo "further on";)->success 0 further on
ivan_pozdeev

2
बाहरी प्रोग्राम को सहेजने के :बजाय bulit-in का उपयोग करें । trueexec
टॉम हेल

@ivan_pozdeev क्या उपयोग करने का कोई तरीका है &&.. ||और फिर भी उनके बीच एक विफल कमांड को पकड़ते हैं?
टॉम हेल

2
@TomHale नंबर &&और ||परिभाषा के अनुसार उनके सामने पूरे कमांड पर लागू होते हैं। इसलिए, यदि आपके पास इसके पहले दो कमांड हैं (चाहे वे कैसे संयुक्त हों), आप इसे केवल उनमें से एक पर लागू नहीं कर सकते हैं और दूसरे पर नहीं। आप कर सकते हैं का अनुकरण if/ then/ elseझंडा चर के साथ तर्क है, लेकिन वहाँ है कि अगर क्यों परेशान if/ then/ elseउचित?
ivan_pozdeev

14

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

let a=b==5?c:d;

स्वाभाविक रूप से, यह केवल चर प्रदान करने के लिए काम करता है; यह अन्य आदेशों पर अमल नहीं कर सकता है।


24
यह ((...)) के बराबर है, इसलिए यह केवल अंकगणितीय अभिव्यक्तियों के लिए मान्य है
drAlberT

13

यहां एक और विकल्प है जहां आपको केवल उस वेरिएबल को निर्दिष्ट करना है जिसे आप एक बार असाइन कर रहे हैं, और इससे कोई फर्क नहीं पड़ता कि आपका असाइनमेंट एक स्ट्रिंग या संख्या है:

VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`

सिर्फ एक विचार। :)


एक प्रमुख नकारात्मक पहलू: यह स्टैडआउट पर भी कब्जा कर लेगा [ test ]। तो निर्माण केवल उपयोग करने के लिए सुरक्षित है यदि आप "जानते हैं" कि कमांड स्टडआउट के लिए कुछ भी आउटपुट नहीं करता है।
ivan_pozdeev

इसके अलावा के रूप में ही stackoverflow.com/questions/3953645/ternary-operator-in-bash/… साथ ही उद्धरण के अंदर उद्धरण और भागने की जरूरत है। अंतरिक्ष-सहिष्णु संस्करण जैसा दिखेगा VARIABLE="`[ test ] && echo \"VALUE_A\" || echo \"VALUE_B\"`"
ivan_pozdeev

8

निम्नलिखित मेरे उपयोग के मामलों के लिए काम करता है:

उदाहरण

$ tern 1 YES NO                                                                             
YES

$ tern 0 YES NO                                                                             
NO

$ tern 52 YES NO                                                                            
YES

$ tern 52 YES NO 52                                                                         
NO

और इस तरह से एक स्क्रिप्ट में इस्तेमाल किया जा सकता है:

RESULT=$(tern 1 YES NO)
echo "The result is $RESULT"

टैन

function show_help()
{
  echo ""
  echo "usage: BOOLEAN VALUE_IF_TRUE VALUE_IF_FALSE {FALSE_VALUE}"
  echo ""
  echo "e.g. "
  echo ""
  echo "tern 1 YES NO                            => YES"
  echo "tern 0 YES NO                            => NO"
  echo "tern "" YES NO                           => NO"
  echo "tern "ANY STRING THAT ISNT 1" YES NO     => NO"
  echo "ME=$(tern 0 YES NO)                      => ME contains NO"
  echo ""

  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$3" ]
then
  show_help
fi

# Set a default value for what is "false" -> 0
FALSE_VALUE=${4:-0}

function main
{
  if [ "$1" == "$FALSE_VALUE" ]; then
    echo $3
    exit;
  fi;

  echo $2
}

main "$1" "$2" "$3"

7
बहुत व्याख्यात्मक। बहुत पूर्ण। बहुत क्रिया। तीन चीजें मुझे पसंद हैं। ;-)
जेसी चिशोल्म

2
ternबैश का हिस्सा है? मैक ऐसा प्रतीत नहीं होता है
गैर

4
हे @ y 者 無極 而 that's - यह बैश स्क्रिप्ट का नाम है - उस "टर्न" सेक्शन को "टर्न" नामक फाइल में सेव करें, फिर chmod 700 ternउसी फोल्डर में रन करें । अब आपके पास ternअपने टर्मिनल में एक कमांड होगी
ब्रैड पार्क्स

8

हम टर्नररी ऑपरेटर के लिए शेल स्क्रिप्टिंग में निम्नलिखित तीन तरीकों का उपयोग कर सकते हैं:

    [ $numVar == numVal ] && resVar="Yop" || resVar="Nop"

Or

    resVar=$([ $numVar == numVal ] && echo "Yop" || echo "Nop")

Or

    (( numVar == numVal ? (resVar=1) : (resVar=0) ))

यह वास्तव में (इन तीन उदाहरणों में से पहला और दूसरा विशेष रूप से) है, इस प्रश्न का सबसे उपयुक्त उत्तर IMHO है।
नेटपिटिका

6

बैश में टर्नरी कंडीशन के लिए एक बहुत ही बेहतरीन सिंटैक्स है:

a=$(( b == 5 ? 123 : 321  ))

दुर्भाग्य से, यह केवल संख्याओं के साथ काम करता है - जहां तक ​​मुझे पता है।



4

यदि आप समान सिंटैक्स चाहते हैं तो आप इसका उपयोग कर सकते हैं

a=$(( $((b==5)) ? c : d ))

यह केवल पूर्णांकों के साथ काम करता है। आप इसे और अधिक सरल रूप में लिख सकते हैं a=$(((b==5) ? : c : d))- $((...))केवल तभी आवश्यक है जब हम अंकगणित के परिणाम को दूसरे चर पर निर्दिष्ट करना चाहते हैं।
19for में 19

2

यहाँ कुछ विकल्प दिए गए हैं:

1- अगर एक लाइन में और उपयोग करें, तो यह संभव है।

if [[ "$2" == "raiz" ]] || [[ "$2" == '.' ]]; then pasta=''; else pasta="$2"; fi

2- इस तरह एक समारोह लिखें:

 # Once upon a time, there was an 'iif' function in MS VB ...

function iif(){
  # Echoes $2 if 1,banana,true,etc and $3 if false,null,0,''
  case $1 in ''|false|FALSE|null|NULL|0) echo $3;;*) echo $2;;esac
}

स्क्रिप्ट का इस तरह से उपयोग करें

result=`iif "$expr" 'yes' 'no'`

# or even interpolating:
result=`iif "$expr" "positive" "negative, because $1 is not true"` 

3- केस जवाब में प्रेरित, अधिक लचीला और एक लाइन का उपयोग होता है:

 case "$expr" in ''|false|FALSE|null|NULL|0) echo "no...$expr";;*) echo "yep $expr";;esac

 # Expression can be something like:     
   expr=`expr "$var1" '>' "$var2"`

2

यहाँ एक सामान्य समाधान है, कि

  • स्ट्रिंग परीक्षणों के साथ भी काम करता है
  • एक अभिव्यक्ति की तरह लगता है
  • स्थिति में विफल होने पर किसी भी सूक्ष्म दुष्प्रभाव से बचा जाता है

संख्यात्मक तुलना के साथ टेस्ट करें

a = $(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)

स्ट्रिंग तुलना के साथ परीक्षण

a = $(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)


1

यह व्लादिमीर के ठीक जवाब की तरह है । यदि आपका "टर्नरी" "अगर सच, स्ट्रिंग, यदि गलत, खाली" का मामला है, तो आप बस कर सकते हैं:

$ c="it was five"
$ b=3
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a

$ b=5
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a
it was five

1

इसका उत्तर देना है: int a = (b == 5) ? c : d;

बस लिखें:

b=5
c=1
d=2
let a="(b==5)?c:d"

echo $a # 1

b=6;
c=1;
d=2;
let a="(b==5)?c:d"

echo $a # 2

याद रखें कि "अभिव्यक्ति" $ (अभिव्यक्ति) के बराबर है


0

एक स्ट्रिंग-उन्मुख विकल्प, जो एक सरणी का उपयोग करता है:

spec=(IGNORE REPLACE)
for p in {13..15}; do
  echo "$p: ${spec[p==14]}";
done

कौन से आउटपुट:

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