فصل 7- بررسی‌ها

7.3- سایر عملگرهای مقایسه

یک عملگر مقایسه باینری دو متغیر یا کمیت را مقایسه می‌کند. توجه نمایید که مقایسه عدد صحیح و مقایسه رشته هر کدام از یک مجموعه عملگرهای متفاوت استفاده می‌کنند.

مقایسه عدد صحیح

‎-eq‎

مساوی است با

if [ "$a" -eq "$b" ]

‎-ne‎

مساوی نیست با

if [ "$a" -ne "$b" ]

‎-gt‎

بزرگتر است از

if [ "$a" -gt "$b" ]

‎-ge‎

بزرگتر یا مساوی است با

if [ "$a" -ge "$b" ]

‎-lt‎

کوچکتر از

if [ "$a" -lt "$b" ]

‎-le‎

کوچکتر یا مساوی است با

if [ "$a" -le "$b" ]

‎<‎

کوچکتر از ( در داخل پرانتزهای دوگانه)

(("$a" < "$b"))

‎<=‎

کوچکتر یا مساوی (داخل پرانتزهای دوگانه)

(("$a" <= "$b"))

‎>‎

بزرگتر از (داخل پرانتزهای دوگانه)

(("$a" > "$b"))

‎>=‎

بزرگتر یا مساوی با (داخل پرانتزهای دوگانه)

(("$a" >= "$b"))


مقایسه رشته‌ای

=

مساوی است با

‎if [ "$a" = "$b" ]‎

Caution

توجه نمایید که فضای سفید = را قاب‌بندی می‌کند.

‎if [ "$a"="$b" ]‎ معادل مورد فوق نیست.

==

مساوی با

‎if [ "$a" == "$b" ]‎

یک مترادف برای = است.

عملگر مقایسه == در میان یک bracket دوتایی بررسی،نسبت به داخل bracketهای منفرد متفاوت رفتار می‌کند.
[[ $a == z* ]]   
# .یعنی الگوی انطباق شروع شود "z" با یک ‎$a‎ صحیح اگر که‎
[[ $a == "z*" ]] 
#         .باشد (انطباق لفظی)‏ ‎z*‎ مساوی ‎$a‎ صحیح است اگر‎

[ $a == z* ]     
#        فایل و تفکیک کلمه رخ می‌دهد‎globbing‎ جانشینی یا
[ "$a" == "z*" ] 
#         .باشد (انطباق لفظی)‏ ‎z*‎ مساوی ‎$a‎ صحیح است اگر

#   ‎Stéphane Chazelas‎ با تشکر از

‎!=‎

مساوی نیست با

‎if [ "$a" != "$b" ]‎

این عملگر در داخل یک ساختار ‎[[ ... ]]‎ انطباق الگو را به کار می‌برد.

‎<‎

کوچکتر از، در ترتیب الفبایی ASCII

‎if [[ "$a" < "$b" ]]‎

‎if [ "$a" \< "$b" ]‎

توجه نمایید که داخل یک ساختار ‎[ ]‎ لازم است ‎<‎ به صورت escaped باشد.

‎>‎

بزرگتر از، در ترتیب الفبایی ASCII

‎if [[ "$a" > "$b" ]]‎

‎if [ "$a" \> "$b" ]‎

توجه کنید که در درون یک ساختار ‎[ ]‎ لازم است ‎>‎ با کاراکتر گریز پوشش داده شود.

برای یک کاربرد از این عملگر مثال ‎27-11‎ را ببینید.

‎-z‎

رشته تهی است، یعنی، طول آن صفر است

 String=''   #  ‎("null")‎ متغیر رشته‌ای با طول صفر‎

if [ -z "$String" ]
then
  echo "\$String is null."
else
  echo "\$String is NOT null."
fi     #  .تهی است ‎$String‎

‎-n‎

رشته تهی نیست.

Caution

بررسی ‎-n‎ نیاز دارد که رشته داخل bracketهای تست نقل‌قولی باشد. به کار بردن یک رشته غیر نقل‌قولی با ‎-z‎، یا حتی رشته غیر نقل‌قولی به تنهایی در bracketهای تست ( مثال ‎7-6‎ را ببینید) معمولاً کار می‌کند، اگر چه این یک شیوه نا امن است. همیشه رشته مورد بررسی را نقل‌قولی کنید. [1]


مثال ‎7-5‎. مقایسه‌های رشته‌ای و حسابی

#!/bin/bash

a=4
b=5

# .می‌توانند به عنوان یک عدد صحیح یا رشته عمل کنند ‎"b"‎ و ‎"a"‎ اینجا‎
#  بین مقایسه حسابی و رشته‌ای مقداری ابهام وجود دارد، چون متغیرهای
#+                             .به طور جدی تعیین نوع نمی‌شوند ‎Bash‎

# عملیات صحیح و مقایسه‌ها را روی متغیرهایی که محتوای ‎Bash‎
#+  .آنها به طور کامل از ارقام تشکیل شده است اجازه می‌دهد‎
#                          .به هرحال، احتیاط شرط عقل است‎

echo

if [ "$a" -ne "$b" ]
then
  echo "$a is not equal to $b"
  echo "(arithmetic comparison)"
fi

echo

if [ "$a" != "$b" ]
then
  echo "$a is not equal to $b."
  echo "(string comparison)"
  #     "4"  != "5"
  # ASCII 52 != ASCII 53
fi

#  .کار می‌کنند ‎"-ne"‎ و ‎"!="‎ در این نمونه خاص هر دو مورد‎

echo

exit 0

مثال ‎7-6‎. بررسی آنکه آیا یک رشته تهی است

#!/bin/bash
#   ‎str-test.sh: 
#               ‎ بررسی رشته‌های تهی و رشته‌های نقل‌قولی نشده، اما 
#                                     ‎if [ ... ]‎ با استفاده از‎ 

#         .اگر یک متغیر ارزش‌گذاری نشده باشد، مقدار مشخصی ندارد‎ 
#     .یا تهی نامیده می‌شود (این همان صفر نیست)‏ ‎(null)‎ این حالت

if [ -n $string1 ]           #  .تعریف یا مقداردهی نگردیده است‎
then
  echo "String \"string1\" is not null."
else  
  echo "String \"string1\" is null."
fi                           #                   .نتیجه اشتباه‎
#مقداردهی نشده، به عنوان غیر تهی نمایش می‌دهد ‎$string1‎ با اینکه‎

echo

#  .بیایید دوباره امتحان کنیم‎

if [ -n "$string1" ]  #         .نقل‌قولی است ‎$string1‎ این دفعه‎
then
  echo "String \"string1\" is not null."
else  
  echo "String \"string1\" is null."
fi                    #!تست را نقل‌قول کنید‎bracket‎ رشته‌های داخل‎

echo

if [ $string1 ]       #      برهنه می‌ماند ‎$string1‎ در این نوبت‎
then
  echo "String \"string1\" is not null."
else  
  echo "String \"string1\" is null."
fi                    #                     این درست کار می‌کند‎ 
#    .به تنهایی، تشخیص می‌دهد که رشته تهی است ‎[ ... ]‎ عملگر تست 
# .شیوه مناسبی است ‎(if [ "$string1" ])‎ به هر حال، نقل‌قولی کردن 
#
#                      :اشاره می‌کند ‎Stephane Chazelas‎ همچنانکه‎ 
#                       "]"‎ دارای یک شناسه است ‎if [ $string1 ] 
#   "]"‎ تهی و "$string1"‎ دارای دو شناسه است، ‎if [ "$string1" ]‎


echo


string1=initialized

if [ $string1 ]            #  نقل‌قولی نشده ‎$string1‎ یکبار دیگر‎
then
  echo "String \"string1\" is not null."
else  
  echo "String \"string1\" is null."
fi                         #         .باز هم، نتیجه درست می‌دهد‎
#       ...کنید، زیرا ‎("$string1")‎ هنوز بهتر است آن را نقل‌قولی‎


string1="a = b"

if [ $string1 ]            #     .نقل‌قول نشده  ‎$string1‎ دوباره‎
then
  echo "String \"string1\" is not null."
else  
  echo "String \"string1\" is null."
fi         #  !نقل‌قولی نشده، نتیجه اشتباه می‌دهد ‎$string1‎ اکنون

exit 0     #    ‎به خاطر هشیاری‌اش ‎Florian Wisser‎ همچنین تشکر از‎

مثال ‎7-7‎. zmore

#!/bin/bash
#  zmore

#             ‎'more'‎‎شده به وسیله فیلتر gzip‎ مرور فایل‌های‎

E_NOARGS=85
E_NOTFOUND=86
E_NOTGZIP=87

if [ $# -eq 0 ]      #    ‎if [ -z "$1" ] :‎همان اثر مشابه‎
#    ‎zmore "" arg2 arg3‎  :می‌تواند موجود، اما تهی باشد ‎$1
then
  echo "Usage: `basename $0` filename" >&2
#                              ‎stderr‎ هدایت پیغام خطا به
  exit $E_NOARGS
#.را به عنوان وضعیت خروج اسکریپت (کد خطا) برگشت می‌دهد ‎85‎
fi  

filename=$1

if [ ! -f "$filename" ]   # .وجود فاصله‌های احتمالی را مجاز می‌کند ‎$filename‎ نقل‌قول‎
then
  echo "File $filename not found!" >&2           #     ‎stderr‎ هدایت پیغام خطا به‎
  exit $E_NOTFOUND
fi  

if [ ${filename##*.} != "gz" ]
#  .به کار بردن ابروها در جایگزینی متغیر‎
then
  echo "File $1 is not a gzipped file!"
  exit $E_NOTGZIP
fi  

zcat $1 | more

         #                         .را به کار می‌برد ‎'more'‎ فیلتر‎
         #          .را جایگزین نمود ‎'less'‎ در صورت تمایل می‌توان

exit $?  # اسکریپت وضعیت خروج لوله را برگشت می‌دهد. در واقع اینجا‎
         #  غیر ضروری است، چون اسکریپت در هر حالت ‎"exit $?"‎ جمله‎
         #+  .وضعیت خروج آخرین فرمان اجرا شده را برگشت خواهد داد‎


مقایسه مرکب

‎-a‎

and منطقی

‎exp1 -a exp2‎ در صورتیکه exp1 و exp2 هر دو صحیح باشند، صحیح را برگشت می‌دهد.

‎-o‎

or منطقی

‎exp1 -o exp2‎ در صورتی صحیح برگشت می‌دهد که هر کدام از exp1 یا exp2 صحیح باشد.

اینها مشابه عملگرهای مقایسه && و || پوسته Bash، استفاده شده در bracketهای دوتایی هستند.

[[ condition1 && condition2 ]]

عملگرهای ‎-o‎ و ‎-a‎ با فرمان test و یا در داخل bracketهای منفرد تست کار می‌کنند.

if [ "$expr1" -a "$expr2" ]
then
  echo "Both expr1 and expr2 are true."
else
  echo "Either expr1 or expr2 is false."
fi


Caution

اما، به طوریکه rihad اشاره می‌کند:

[ 1 -eq 1 ] && [ -n "`echo true 1>&2`" ]    #       true
[ 1 -eq 2 ] && [ -n "`echo true 1>&2`" ]    #       (بدون خروجی)
# ^^^^^^^ .شرط غلط. تا اینجا همه چیز همانطور است که انتظار می‌رود‎

#                          ... اما‎
[ 1 -eq 2 -a -n "`echo true 1>&2`" ]        #       true
# ^^^^^^^                است؟ ‎"true"‎ شرط غلط. بنابراین چرا خروجی

#          آیا به علت این است که هر دو عبارت شرط ارزیابی می‌شوند؟‎
[[ 1 -eq 2 && -n "`echo true 1>&2`" ]]      #       (بدون خروجی)
                                            #  .خیر، اینطور نیست

#    .نیستند ‎-a‎ و ‎-o‎ ‏«اتصال‌کوتاه» هستند، در حالیکه ‎&&‎ و ‎||‎ ظاهراً‎

برای دیدن عملگرهای مقایسه مرکب در عمل، به مثال ‎8-3‎‏، مثال ‎27-17‎‏، و مثال ‎A-29‎ مراجعه کنید.

یادداشت‌ها

[1]

به طوریکه ‎S.C.‎ اشاره می‌کند، در یک بررسی مرکب، حتی نقل‌قول رشته متغیر شاید کفایت نکند. ‎[ -n "$string" -o "$a" = "$b" ]‎ در صورتیکه ‎$string‎ تهی باشد، در برخی از نگارش‌های Bash می‌تواند موجب یک خطابشود. روش بی‌خطر، الحاق نمودن یک کاراکتر اضافی به متغیرهای تهی احتمالی است، ‎[ "x$string" != x -o "x$a" = "x$b" ]‎ ‏( ‎"x"‎ها با هم خنثی می‌شوند).