كيف يمكن تمثيل شروط متعددة في جملة if؟

سئل على ٣٠ سبتمبر ٢٠١٠  ·  تمت مشاهدة 894.8k مرة  ·  مصدر

user389955 picture
في ٣٠ سبتمبر ٢٠١٠

أريد أن أمثل شروطًا متعددة مثل هذا:

if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]   
then  
    echo abc;  
else  
    echo efg;   
fi  

ولكن عندما أقوم بتنفيذ البرنامج النصي ، فإنه يظهر

syntax error at line 15: `[' unexpected, 

حيث السطر 15 هو الذي يظهر إذا ...

ما هو الخطأ في هذا الشرط؟ أعتقد أن هناك خطأ ما في () .

الإجابات

Jonathan Leffler picture
في ٣٠ سبتمبر ٢٠١٠
400

التقنية الكلاسيكية (الهروب من الحروف الأولية):

if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi

لقد أرفقت الإشارات إلى $g علامتي اقتباس ؛ هذه ممارسة جيدة بشكل عام. بدقة ، الأقواس ليست ضرورية لأن أسبقية -a و -o تجعلها صحيحة حتى بدونها.

لاحظ أن المشغلين -a و -o جزء من مواصفات POSIX لـ test ، ويعرف أيضًا باسم [ ، بشكل أساسي للتوافق مع الإصدارات السابقة (نظرًا لأنهم كانوا جزءًا من test في الإصدار السابع من UNIX ، على سبيل المثال) ، ولكن تم وضع علامة عليها بوضوح على أنها "قديمة" بواسطة POSIX. يبدو أن Bash (انظر التعبيرات الشرطية ) تستبق المعاني الكلاسيكية و POSIX لـ -a و -o مع مشغليها البديلين الذين يأخذون الحجج.


مع بعض العناية ، يمكنك استخدام عامل التشغيل الأحدث [[ ، لكن كن على دراية بأن الإصدارات في Bash و Korn Shell (على سبيل المثال) لا يجب أن تكون متطابقة.

for g in 1 2 3
do
    for c in 123 456 789
    do
        if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
        then echo "g = $g; c = $c; true"
        else echo "g = $g; c = $c; false"
        fi
    done
done

مثال على التشغيل باستخدام Bash 3.2.57 على نظام التشغيل Mac OS X:

g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false

لا تحتاج إلى اقتباس المتغيرات في [[ كما تفعل مع [ لأنه ليس أمرًا منفصلاً بنفس طريقة [ .


أليس هذا سؤال كلاسيكي؟

كان يمكن أن أفكر بذلك. ومع ذلك ، هناك بديل آخر وهو:

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi

في الواقع ، إذا قرأت إرشادات 'shell portable' لأداة autoconf أو الحزم ذات الصلة ، فإن هذا الترميز - باستخدام ' || ' و ' && ' - هو ما يوصون به . أفترض أنه يمكنك حتى الذهاب إلى أبعد من ذلك:

if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi

عندما تكون الإجراءات تافهة مثل الصدى ، فهذا ليس سيئًا. عندما تكون كتلة الإجراء المراد تكرارها عبارة عن أسطر متعددة ، يكون التكرار مؤلمًا جدًا ويفضل استخدام أحد الإصدارات السابقة - أو تحتاج إلى التفاف الإجراءات في دالة يتم استدعاؤها في كتل then .

Paused until further notice. picture
في ٣٠ سبتمبر ٢٠١٠
194

في باش:

if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
sunitha picture
في ٢١ يناير ٢٠١٥
41

باستخدام /bin/bash سوف يعمل ما يلي:

if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
    echo "Entered $option"
fi
orkoden picture
في ١٥ نوفمبر ٢٠١٣
9

كن حذرًا إذا كان لديك مسافات في متغيرات السلسلة الخاصة بك وتحقق من وجودها. تأكد من اقتباسها بشكل صحيح.

if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
ghostdog74 picture
في ٣٠ سبتمبر ٢٠١٠
6
$ g=3
$ c=133
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
efg
$ g=1
$ c=123
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
abc
Ashan Priyadarshana picture
في ١٤ أكتوبر ٢٠١٩
2

في bash for string مقارنة ، يمكنك استخدام التقنية التالية.

if [ $var OP "val" ]; then
    echo "statements"
fi

مثال:

var="something"
if [ $var != "otherthing" ] && [ $var != "everything" ] && [ $var != "allthings" ]; then
    echo "this will be printed"
else
    echo "this will not be printed"
fi
Debjyoti Banerjee picture
في ١٨ مايو ٢٠١٧
0
#!/bin/bash

current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print $5'} )
echo $current_usage
critical_usage=6%
warning_usage=3%

if [[ ${current_usage%?} -lt ${warning_usage%?} ]]; then
echo OK current usage is $current_usage
elif [[ ${current_usage%?} -ge ${warning_usage%?} ]] && [[ ${current_usage%?} -lt ${critical_usage%?} ]]; then
echo Warning $current_usage
else
echo Critical $current_usage
fi
Yordan Georgiev picture
في ٢٤ مايو ٢٠٢٠
0

يمكنك أيضًا ربط أكثر من شرطين:

if [ \( "$1" = '--usage' \) -o \( "$1" = '' \) -o \( "$1" = '--help' \) ]
then
   printf "\033[2J";printf "\033[0;0H"
   cat << EOF_PRINT_USAGE

   $0 - Purpose: upsert qto http json data to postgres db

   USAGE EXAMPLE:

   $0 -a foo -a bar



EOF_PRINT_USAGE
   exit 1
fi