उलटी बूलियन चर


26

मैं सरल स्क्रिप्ट की कोशिश करना चाहता हूं

flag=false
while !$flag
do
   read x
   if [ "$x" -eq "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

लेकिन जब मैं इसे चलाता हूं, अगर मैं टाइप करता हूं, तो मैं इसे trueदेखूंगा x="true"और flag="true", लेकिन चक्र समाप्त नहीं होगा। स्क्रिप्ट में क्या गलत है? मैं बूलियन चर को ठीक से कैसे उलट सकता हूं?



धन्यवाद! मुझे अब यह मिल गया है
8

जवाबों:


21

आपकी स्क्रिप्ट में दो त्रुटियां हैं। पहला यह है कि आप के बीच एक जगह की जरूरत है !और $flagनामक आदेश के लिए, नहीं तो खोल दिखता है !$flag। दूसरी त्रुटि यह है कि -eqपूर्णांक तुलना के लिए है, लेकिन आप इसे एक स्ट्रिंग पर उपयोग कर रहे हैं। आपके शेल के आधार पर, या तो आपको एक त्रुटि संदेश दिखाई देगा और लूप हमेशा के लिए जारी रहेगा क्योंकि स्थिति [ "$x" -eq "true" ]सत्य नहीं हो सकती है, या प्रत्येक गैर-पूर्णांक मान 0 के रूप में माना जाएगा और यदि आप किसी स्ट्रिंग (सहित false) में प्रवेश करेंगे तो लूप बाहर निकल जाएगा 0 से भिन्न संख्या के अलावा।

जबकि ! $flagसही है, तो यह एक बुरा विचार एक कमांड के रूप में एक स्ट्रिंग के इलाज के लिए है। यह काम करेगा, लेकिन यह आपकी स्क्रिप्ट में बदलाव के लिए बहुत संवेदनशील होगा, क्योंकि आपको यह सुनिश्चित करना होगा कि $flagकभी भी trueया कुछ भी नहीं हो सकता है false। यहां एक स्ट्रिंग तुलना का उपयोग करना बेहतर होगा, जैसे नीचे दिए गए परीक्षण में।

flag=false
while [ "$flag" != "true" ]
do
   read x
   if [ "$x" = "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

आपके द्वारा दिए गए तर्क को व्यक्त करने का एक बेहतर तरीका है। उदाहरण के लिए, आप एक अनंत लूप बना सकते हैं और समाप्ति की स्थिति का पता लगाने पर इसे तोड़ सकते हैं।

while true; do
  read -r x
  if [ "$x" = "true" ]; then break; fi
  echo "$x: false"
done

साथ [की अंतर्निहित ksh, [ x -eq y ]अगर सच लौट xअंकगणितीय अभिव्यक्ति का निराकरण के रूप में एक ही नंबर के लिए yतो उदाहरण के लिए गणित अभिव्यक्ति x=2 true=1+1 ksh -c '[ x -eq true ] && echo yes'होगा उत्पादन हाँ।
स्टीफन चेज़लस

10

जबकि बाश में कोई बूलियन चर नहीं हैं, अंकगणित मूल्यांकन का उपयोग करके उनका अनुकरण करना बहुत आसान है।

flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)

if ((flag)) # Test for True
then
  : # do something
fi

if ! ((flag)) # Test for False
then
  : # do something
fi

flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)

यह भी ksh में काम करता है। मुझे आश्चर्य नहीं होगा अगर यह सभी POSIX- संगत गोले में काम करता है, लेकिन मानक की जांच नहीं की है।


1
! ! ((val))Bash में काम करता है , जैसे C या C ++ में? उदाहरण के लिए, यदि val0 है तो वह 0 रहता है ! !। अगर val1 है तो 1 रह जाता है ! !। अगर val8 है तो इसे 1 के बाद नीचे खींच लिया जाता है ! !। या क्या मुझे एक और सवाल पूछने की ज़रूरत है?

1
-1 | पोसिक्स श में, स्टैंडअलोन (..) अपरिभाषित है; कृपया इसके संदर्भ को हटा दें
LinuxSecurityFreak

Vlastimil प्रश्न विशेष रूप से बैश के बारे में है - पॉज़िक्स शेल नहीं। जब उस विषय के बारे में सवाल नहीं है तो वोट डाउन क्यों करें?
निक बुल

6

यदि आप पूरी तरह से सुनिश्चित कर सकते हैं कि चर में 0 या 1 होगा, तो आप दो मानों के बीच फ्लिप करने के लिए बिटवाइज़ XOR- समान ऑपरेटर का उपयोग कर सकते हैं:

$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0

2

यह मेरे लिए काम करता है:

flag=false
while [[ "$flag" == "false" ]]
do
   read x
   if [[ "$x" == "true" ]]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

लेकिन, वास्तव में, आपको क्या करना चाहिए while:

while ! $flag

0

शेल में बूलियन चर की कोई अवधारणा नहीं है।
शैल चर केवल हो सकता है text(एक स्ट्रिंग), और, कुछ मामलों में, कि पाठ (एक पूर्णांक के रूप में व्याख्या की जा सकती है 1, 0xa, 010, आदि)।

इसलिए, flag=trueइसका तात्पर्य है कि शेल में कोई सत्यता या मिथ्याता नहीं है।

तार

क्या किया जा सकता है या तो एक स्ट्रिंग तुलना है [ "$flag" == "true" ]या कुछ कमांड में चर सामग्री का उपयोग करें और इसके परिणामों की जांच करें , जैसे निष्पादित करें true(क्योंकि दोनों निष्पादन योग्य कहलाते हैं trueऔर एक कहा जाता हैfalse ) एक कमांड के रूप में और जांचें कि क्या उस कमांड का निकास कोड शून्य है (सफल)।

$flag; if [ "$?" -eq 0 ]; then ... fi

या कम:

if "$flag"; then ... fi

यदि चर की सामग्री का उपयोग एक कमांड के रूप में किया जाता है !, तो कमांड का निकास स्थिति को नकारने के लिए इस्तेमाल किया जा सकता है, अगर एक जगह के बीच में एक! cmd ), जैसे:

if ! "$flag"; then ... fi

स्क्रिप्ट को बदलना चाहिए:

flag=false
while ! "$flag" 
do
   read x
   if [ "$x" == "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

पूर्णांक

संख्यात्मक मान और अंकगणितीय विस्तार का उपयोग करें

इस स्थिति में, का बाहर निकलें कोड $((0))है 1और बाहर निकलने का कोड $((1))है 0
बैश, ksh और zsh में अंकगणित को एक के अंदर किया जा सकता है ((..))(ध्यान दें कि शुरुआत $गायब है)।

flag=0; if ((flag)); then ... fi

इस कोड का एक पोर्टेबल संस्करण अधिक जटिल है:

flag=0; if [ "$((flag))" -eq 0 ]; then ... fi      # test for a number
flag=0; if [ "$((flag))"  == 0 ]; then ... fi      # test for the string "0"

बाश / क्षश / zsh में आप कर सकते हैं:

flag=0    
while ((!flag)) 
do
   read x
   [ "$x" == "true" ] && flag=1
   echo "${x} : ${flag}"
done

वैकल्पिक रूप से

आप "एक बूलियन चर उल्टा" कर सकते हैं (बशर्ते इसमें एक संख्यात्मक मान हो):

((flag=!flag))

वह या तो के मूल्य को बदल देगा या ।flag01


नोट : कृपया अपने कोड को प्रश्न के रूप में पोस्ट करने से पहले https://www.shellcheck.net/ में त्रुटियों की जांच करें , कई बार समस्या को खोजने के लिए पर्याप्त है।


0

untilके लिए कम है while !(और until, इसके विपरीत !बॉर्न है), इसलिए आप कर सकते हैं:

flag=false
until "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done

जो समान होना चाहिए:

flag=false
while ! "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done

आप इसे भी लिख सकते हैं:

until
   IFS= read -r x
   printf '%s\n' "$x"
   [ "$x" = true ]
do
   continue
done

until/ whileऔर के बीच का हिस्साdo एक भी कमांड नहीं होना चाहिए।

!POSIX शेल सिंटैक्स में एक कीवर्ड है। इसे सीमांकित करने की आवश्यकता है, एक टोकन जो इस प्रकार से अलग होता है और एक पाइपलाइन से पहले का पहला टोकन होता है ( ! foo | barपाइपलाइन के लिए नकारात्मक औरfoo | ! bar यह अमान्य है हालांकि कुछ गोले इसे विस्तार के रूप में स्वीकार करते हैं)।

!true!trueकमांड के रूप में व्याख्या की जाती है, जो मौजूद होने की संभावना नहीं है। ! trueकार्य करना चाहिए। !(true)POSIX-compliant गोले में काम करना चाहिए क्योंकि यह !एक सीमांकक के बाद सीमांकित है (, लेकिन व्यवहार में यह काम नहीं करता है ksh/ bash -O extglobजहां यह !(pattern)विस्तारित ग्लोब ऑपरेटर के साथ संघर्ष करता है और न ही zsh (sh emulation को छोड़कर) के साथ जहां और glob(qualifiers)साथ संघर्ष करता है के बिना।bareglobqualglob(group)


-1
[ ${FOO:-0} == 0 ] && FOO=1 || FOO=0

या और भी:

[ ${FOO:-false} == false ] && FOO=true || FOO=false

काम करना चाहिए

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