ฉันกำลังมองหาโอเปอเรเตอร์“ in” ที่ใช้งานได้เช่นนี้:
if [ "$1" in ("cat","dog","mouse") ]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
เห็นได้ชัดว่ามันเป็นคำสั่งที่สั้นกว่าเมื่อเปรียบเทียบกับพูดโดยใช้การทดสอบหลาย ๆ แบบหรือ
ฉันกำลังมองหาโอเปอเรเตอร์“ in” ที่ใช้งานได้เช่นนี้:
if [ "$1" in ("cat","dog","mouse") ]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
เห็นได้ชัดว่ามันเป็นคำสั่งที่สั้นกว่าเมื่อเปรียบเทียบกับพูดโดยใช้การทดสอบหลาย ๆ แบบหรือ
คำตอบ:
คุณสามารถใช้case
...esac
$ cat in.sh
#!/bin/bash
case "$1" in
"cat"|"dog"|"mouse")
echo "dollar 1 is either a cat or a dog or a mouse"
;;
*)
echo "none of the above"
;;
esac
อดีต
$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above
ด้วยksh
, bash -O extglob
หรือzsh -o kshglob
คุณยังสามารถใช้รูปแบบการ glob ขยาย:
if [[ "$1" = @(cat|dog|mouse) ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
else
echo "none of the above"
fi
ด้วยbash
, ksh93
หรือzsh
คุณยังสามารถใช้การเปรียบเทียบการแสดงออกปกติ:
if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
else
echo "none of the above"
fi
=~
ไม่ถูกต้องในการทดสอบวงเล็บเดี่ยว POSIX
[
เป็นเพียงPOSIX แต่[[
เป็นคุณสมบัติเพิ่มเติมของ bash, ksh (เห็นได้ชัดว่ามันมีต้นกำเนิดมาจากที่นั่นและ zsh. case
ตัวอย่างคือ POSIX ส่วนใหญ่ของทั้งหมดแม้ว่า
case "$1" in
ไม่จำเป็นต้องอ้างสิทธิ์ $ 1 ในไม่มีการแยกคำหรือการขยายชื่อพา ธ ในโทเค็นนั้น
ไม่มีการทดสอบแบบ "ใน" ในการทุบตี แต่มีการทดสอบ regex (ไม่ใช่ในแบบ Bourne):
if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
และมักเขียนโดยใช้ตัวแปร (มีปัญหาน้อยลงกับการอ้างอิง):
regex='^(cat|dog|mouse)$'
if [[ $1 =~ $regex ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
สำหรับเชลล์เป้าหมายที่เก่ากว่าคุณต้องใช้การจับคู่เคส:
case $1 in
cat|dog|mouse) echo "dollar 1 is either a cat or a dog or a mouse";;
esac
การใช้ a case
นั้นทำได้ดีและดีถ้าคุณมีสัตว์เลี้ยงที่คุณต้องการจับคู่ แต่จะไม่ทำงานหากคุณต้องการสร้างรูปแบบในรันไทม์เนื่องจากcase
ไม่ตีความการสลับจากภายในพารามิเตอร์ที่ขยาย
สิ่งนี้จะจับคู่เฉพาะสตริงตัวอักษรcat|dog|mouse
:
patt='cat|dog|mouse'
case $1 in
$patt) echo "$1 matches the case" ;;
esac
อย่างไรก็ตามคุณสามารถใช้ตัวแปรกับนิพจน์ทั่วไปที่ตรงกันได้ ตราบใดที่ตัวแปรไม่ได้ถูกยกมาตัวดำเนินการ regex ใด ๆ ที่อยู่ภายในจะมีความหมายพิเศษ
patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
echo "$1 matches the pattern"
fi
คุณสามารถใช้อาเรย์แบบเชื่อมโยงได้ การตรวจสอบว่ามีคีย์อยู่ในคีย์นั้นเป็นสิ่งที่ใกล้เคียงที่สุดกับin
โอเปอเรเตอร์ที่ Bash ระบุหรือไม่ แม้ว่าไวยากรณ์จะค่อนข้างน่าเกลียด:
declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1
if [ "${arr[$1]+x}" ]; then
echo "$1 is in the array"
fi
คุณสามารถใช้case
คำสั่งในการif
ทดสอบ แต่รหัสจะมีลักษณะขนเล็กน้อย:
if case "$1" in (cat|dog|mouse) true ;; (*) false; esac; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
หรือสั้นกว่าเล็กน้อย
if ! case "$1" in (cat|dog|mouse) false; esac; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
นี่เป็นการใช้ส่วนcase
คำสั่งเพียงเพื่อทำการจับคู่รูปแบบสำหรับส่วนif
คำสั่ง แนะนำการทดสอบจริง / เท็จที่ไม่จำเป็น
มันจะดีกว่าที่จะใช้เพียงcase
:
case "$1" in
cat|dog|mouse)
printf '"%s" is one of cat, dog or mouse\n' "$1"
;;
*)
printf '"%s" is unknown\n' "$1"
esac
อย่าทำสิ่งนี้:
is_one_of () {
eval "case $1 in ($2) return 0; esac"
return 1
}
if is_one_of "$1" 'cat|dog|mouse'; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
หรือสิ่งนี้:
is_one_of () (
word=$1
shift
IFS='|'
eval "case $word in ($*) return 0; esac"
return 1
)
if is_one_of "$1" cat dog mouse; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
... เนื่องจากคุณกำลังเพิ่ม cruft ที่อันตรายมากขึ้นเพื่อให้สามารถใช้if
คำสั่งในรหัสของคุณแทนcase
คำสั่งที่สมเหตุสมผลอย่างสมบูรณ์
eval
ของcase
คำสั่งในกรณีนี้และมันจะยิ่งมีแนวโน้มที่จะเกิดข้อผิดพลาด
"$1"|"$2"|"$3"
ในกรณีนี้มีรูปแบบที่เรียบง่ายแต่ละอาจจะผ่านเป็นพารามิเตอร์ตำแหน่งที่จะทำงานและทำ ยังunix.stackexchange.com/a/234415/85039 แต่ใช่มันมีขนเล็กน้อย
grep
เข้าใกล้
if echo $1 | grep -qE "^(cat|dog|mouse)$"; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
-q
เพื่อหลีกเลี่ยงผลลัพธ์ไปยังหน้าจอใด ๆ (เร็วกว่าการพิมพ์>/dev/null
)-E
สำหรับ(cat|dog|mouse)
ด้านการแสดงออกปกติขยายความต้องการนี้^(cat|dog|mouse)$
ตรงกับบรรทัดใด ๆ ที่เริ่มต้น ( ^
) กับแมวสุนัขหรือเมาส์ ( (cat|dog|mouse)
) ตามด้วยท้ายบรรทัด ( $
)