วิธีใช้การทดสอบแบบมีเงื่อนไข Double Bracket ใน Linux

เผยแพร่แล้ว: 2022-01-29
fatmawati achmad zaenuri/Shutterstock.com

การทดสอบแบบมีเงื่อนไขจะแยกกระแสการดำเนินการของสคริปต์ Linux Bash ตามผลลัพธ์ของนิพจน์เชิงตรรกะ การทดสอบแบบมีเงื่อนไขวงเล็บคู่ทำให้ไวยากรณ์ง่ายขึ้นมาก—แต่ยังมี gotchas ของตัวเอง

วงเล็บเดี่ยวและคู่

Bash ให้คำสั่ง test ซึ่งช่วยให้คุณทดสอบนิพจน์เชิงตรรกะได้ นิพจน์จะส่งกลับคำตอบที่ระบุการตอบสนองจริงหรือเท็จ การตอบสนองที่แท้จริงจะถูกระบุด้วยค่าที่ส่งกลับเป็นศูนย์ สิ่งใดที่ไม่ใช่ศูนย์แสดงว่าเป็นเท็จ

การโยงคำสั่งบนบรรทัดคำสั่งด้วยตัวดำเนินการ && จะใช้คุณสมบัตินี้ คำสั่งจะดำเนินการได้ก็ต่อเมื่อคำสั่งก่อนหน้าเสร็จสมบูรณ์เท่านั้น

หากการทดสอบเป็นจริง คำว่า "ใช่" จะถูกพิมพ์ออกมา

 ทดสอบ 15 -eq 15 && echo "ใช่"
 ทดสอบ 14 -eq 15 && echo "ใช่" 

ตัวอย่างง่ายๆ ของคำสั่งทดสอบ Bash

การทดสอบแบบมีเงื่อนไขวงเล็บเดียวเลียนแบบคำสั่ง test พวกเขาใส่นิพจน์ในวงเล็บ " [ ] ” และดำเนินการเหมือนกับคำสั่ง test อันที่จริงมันเป็นโปรแกรมเดียวกัน ซึ่งสร้างจากซอร์สโค้ดเดียวกัน ความแตกต่างในการปฏิบัติงานเพียงอย่างเดียวคือวิธีที่เวอร์ชัน test และ [ เวอร์ชันจัดการคำขอความช่วยเหลือ

นี่คือจากซอร์สโค้ด:

 /* รับรู้ --help หรือ --version แต่เมื่อเรียกใช้ใน .เท่านั้น
แบบฟอร์ม "[" เมื่ออาร์กิวเมนต์สุดท้ายไม่ใช่ "]" ใช้โดยตรง
แยกวิเคราะห์ แทนที่จะ parse_long_options เพื่อหลีกเลี่ยงการยอมรับ
ตัวย่อ POSIX อนุญาต "[ --help" และ "[ --version" ถึง
มีพฤติกรรม GNU ตามปกติ แต่ต้องใช้ "test --help"
และ "test --version" เพื่อออกอย่างเงียบ ๆ ด้วยสถานะ 0 */
โฆษณา

เราสามารถเห็นผลของสิ่งนี้ได้โดยขอ test และ [ เพื่อขอความช่วยเหลือและตรวจสอบรหัสตอบกลับที่ส่งไปยัง Bash

 ทดสอบ --help
 เสียงสะท้อน $?
 [ --ช่วย
 เสียงสะท้อน $? 

ใช้ --help ในการทดสอบและ [

ทั้ง test และ [ เป็น shell buildins ซึ่งหมายความว่าพวกมันถูกอบใน Bash แต่ยังมีเวอร์ชันไบนารีแบบสแตนด์อโลนของ [ .

 แบบทดสอบ
 พิมพ์ [
 อยู่ไหน [ 

ค้นหาประเภทต่าง ๆ ของ [ และคำสั่งทดสอบ

ในทางตรงกันข้าม การทดสอบเงื่อนไขวงเล็บคู่ [[ และ ]] คือ คีย์เวิร์ด [[ และ ]] ทำการทดสอบเชิงตรรกะเช่นกัน แต่ไวยากรณ์ต่างกัน เนื่องจากเป็นคีย์เวิร์ด คุณจึงใช้ฟีเจอร์ที่เรียบร้อยซึ่งใช้ไม่ได้ในเวอร์ชันวงเล็บปีกกาเดียว

คำหลักวงเล็บคู่ได้รับการสนับสนุนโดย Bash แต่ไม่มีอยู่ในทุกเชลล์อื่น ตัวอย่างเช่น Korn เชลล์สนับสนุนพวกเขา แต่เชลล์แบบเก่าธรรมดา sh ไม่สนับสนุน สคริปต์ทั้งหมดของเราเริ่มต้นด้วยบรรทัด:

 #!/bin/bash

เพื่อให้แน่ใจว่าเรากำลังเรียกใช้ Bash shell เพื่อเรียกใช้สคริปต์

ที่เกี่ยวข้อง: วิธีสร้างและเรียกใช้ Bash Shell Scripts บน Windows 10

บิวอินและคีย์เวิร์ด

เราสามารถใช้โปรแกรม compgen เพื่อแสดงรายการบิวด์อิน:

 compgen -b | fmt -w 70
โฆษณา

หากไม่มีการวางท่อเอาต์พุตผ่าน fmt เราจะได้รับรายการยาว ๆ ที่แต่ละบิวด์อินอยู่ในบรรทัดของตัวเอง ในกรณีนี้จะสะดวกกว่าในการดูบิวด์อินที่จัดกลุ่มเข้าด้วยกันเป็นย่อหน้า

แสดงรายการ Bash builtins

เราสามารถเห็น test และ [ ในรายการ แต่ ] ไม่อยู่ในรายการ คำสั่ง [ ค้นหาการปิด ] เพื่อตรวจจับเมื่อถึงจุดสิ้นสุดของนิพจน์ แต่ ] ไม่ใช่บิวด์อินแยกต่างหาก เป็นเพียงสัญญาณที่เราให้กับ [ เพื่อระบุจุดสิ้นสุดของรายการพารามิเตอร์

หากต้องการดูคำหลัก เราสามารถใช้:

 compgen -k | fmt -w 70 

แสดงรายการคำหลัก Bash

คีย์เวิร์ด [[ และ ]] อยู่ในรายการ เนื่องจาก [[ เป็นคีย์เวิร์ดเดียวและ ]] เป็นคีย์เวิร์ดอื่น เป็นคู่ที่ตรงกัน เช่นเดียวกับ if และ fi และ case และ esac

เมื่อ Bash กำลังแยกวิเคราะห์สคริปต์หรือบรรทัดคำสั่ง และตรวจพบคีย์เวิร์ดที่มีคีย์เวิร์ดปิดที่ตรงกัน คีย์เวิร์ดปิดจะรวบรวมทุกอย่างที่ปรากฏระหว่างคีย์เวิร์ดและใช้การดูแลพิเศษที่คีย์เวิร์ดรองรับ

ด้วย buildin สิ่งที่ตามมาหลังคำสั่ง buildin จะถูกส่งต่อเหมือนกับพารามิเตอร์ของโปรแกรมบรรทัดคำสั่งอื่นๆ ซึ่งหมายความว่าผู้เขียนสคริปต์ต้องใช้ความระมัดระวังเป็นพิเศษเกี่ยวกับสิ่งต่าง ๆ เช่นช่องว่างในค่าตัวแปร

Shell Globbing

การทดสอบแบบมีเงื่อนไขวงเล็บคู่สามารถใช้เปลือกโลกกลมได้ ซึ่งหมายความว่าเครื่องหมายดอกจัน “ * ” จะขยายเพื่อหมายถึง “อะไรก็ได้”

โฆษณา

พิมพ์หรือคัดลอกข้อความต่อไปนี้ลงในโปรแกรมแก้ไขและบันทึกลงในไฟล์ชื่อ "whelkie.sh"

 #!/bin/bash

stringvar="เวลกี บรูคส์"

ถ้า [[ "$stringvar" == *elk* ]];
แล้ว
  echo "คำเตือนมีอาหารทะเล"
อื่น
  echo "ปราศจากหอย"
fi

ในการทำให้สคริปต์ทำงานได้ เราจำเป็นต้องใช้คำสั่ง chmod พร้อมตัวเลือก -x (ดำเนินการ) คุณจะต้องทำเช่นนี้กับสคริปต์ทั้งหมดในบทความนี้หากต้องการทดลองใช้

 chmod +x whelkie.sh 

การใช้ chmod เพื่อทำให้สคริปต์ปฏิบัติการได้

เมื่อเราเรียกใช้สคริปต์ เราจะเห็นสตริง "elk" ที่พบในสตริง "Whelkie" โดยไม่คำนึงถึงอักขระอื่นที่อยู่ล้อมรอบ

 ./whelkie.sh 

การรันสคริปต์ whelkie.sh

ประเด็นหนึ่งที่ควรทราบคือ เราไม่ตัดสตริงการค้นหาด้วยเครื่องหมายคำพูดคู่ ถ้าคุณทำเช่นนั้น globbing จะไม่เกิดขึ้น สตริงการค้นหาจะได้รับการปฏิบัติอย่างแท้จริง

อนุญาตให้ใช้เปลือกหอยรูปแบบอื่นได้ เครื่องหมายคำถาม “ ? ” จะจับคู่อักขระเดี่ยว และใช้วงเล็บเหลี่ยมเดี่ยวเพื่อระบุช่วงของอักขระ ตัวอย่างเช่น หากคุณไม่ทราบว่าจะใช้กรณีใด คุณสามารถครอบคลุมเหตุการณ์ทั้งสองด้วยช่วง

 #!/bin/bash

stringvar="ฌอง-คล็อด ฟาน แคลม"

ถ้า [[ "$stringvar" == *[cC]lam* ]];
แล้ว
  echo "คำเตือนมีอาหารทะเล"
อื่น
  echo "ปราศจากหอย"
fi

บันทึกสคริปต์นี้เป็น "damme.sh" และทำให้สามารถเรียกใช้งานได้ เมื่อเราเรียกใช้คำสั่งเงื่อนไขจะแก้ไขเป็นจริง และประโยคแรกของคำสั่ง if จะถูกดำเนินการ

 ./damme.sh 

การรันสคริปต์ damme.sh

สตริงอ้างอิง

เราพูดถึงการห่อสตริงด้วยเครื่องหมายคำพูดคู่ก่อนหน้านี้ หากคุณทำเช่นนั้น เปลือกโลกจะไม่เกิดขึ้น แม้ว่าแบบแผนจะบอกว่าเป็นแนวปฏิบัติที่ดี คุณไม่ จำเป็นต้อง ใส่ตัวแปรสตริงในเครื่องหมายคำพูดเมื่อใช้ [[ และ ]] แม้ว่าจะมีการเว้นวรรคก็ตาม ดูตัวอย่างต่อไป ทั้งตัวแปรสตริง $stringvar และ $surname มีการเว้นวรรค แต่ไม่มีการอ้างอิงในคำสั่งเงื่อนไข

 #!/bin/bash

stringvar="แวน Damme"
นามสกุล = "แวน Damme"

ถ้า [[ $stringvar == $นามสกุล ]];
แล้ว
echo "นามสกุลตรงกัน"
อื่น
echo "นามสกุลไม่ตรงกัน"
fi
โฆษณา

บันทึกสิ่งนี้ลงในไฟล์ชื่อ “surname.sh” และทำให้สามารถเรียกใช้งานได้ เรียกใช้โดยใช้:

 ./นามสกุล.sh 

การเรียกใช้สคริปต์นามสกุล.sh

แม้ว่าสตริงทั้งสองจะมีช่องว่าง แต่สคริปต์ก็สำเร็จและคำสั่งแบบมีเงื่อนไขจะแก้ไขเป็นจริง สิ่งนี้มีประโยชน์เมื่อต้องจัดการกับพาธและชื่อไดเร็กทอรีที่มีช่องว่าง ในที่นี้ อ็อพชัน -d คืนค่า จริง หากตัวแปรมีชื่อไดเร็กทอรีที่ถูกต้อง

 #!/bin/bash

dir="/home/dave/Documents/Needs Work"

ถ้า [[ -d ${dir} ]];
แล้ว
  echo "ไดเร็กทอรีได้รับการยืนยัน"
อื่น
  echo "ไม่พบไดเร็กทอรี"
fi

หากคุณเปลี่ยนเส้นทางในสคริปต์เพื่อให้สะท้อนถึงไดเร็กทอรีบนคอมพิวเตอร์ของคุณเอง ให้บันทึกข้อความลงในไฟล์ชื่อ "dir.sh" และทำให้เป็นไฟล์เรียกทำงาน คุณจะเห็นว่าวิธีนี้ใช้ได้ผล

 ./dir.sh 

การรันสคริปต์ dir.sh

ที่เกี่ยวข้อง: วิธีทำงานกับตัวแปรใน Bash

ชื่อไฟล์ Globbing Gotchas

ความแตกต่างที่น่าสนใจระหว่าง [ ] และ [[ ]] เกี่ยวข้องกับชื่อไฟล์ที่มีการวนซ้ำ แบบฟอร์ม “*.sh” จะตรงกับไฟล์สคริปต์ทั้งหมด การใช้วงเล็บเดียว [ ] จะล้มเหลว เว้นแต่จะมีไฟล์สคริปต์เดียว การค้นหาสคริปต์มากกว่าหนึ่งรายการทำให้เกิดข้อผิดพลาด

นี่คือสคริปต์ที่มีเงื่อนไขวงเล็บเดียว

 #!/bin/bash

ถ้า [ -a *.sh ];
แล้ว
  echo "พบไฟล์สคริปต์"
อื่น
  echo "ไม่พบไฟล์สคริปต์"
fi

เราบันทึกข้อความนี้ลงใน "script.sh" และทำให้ใช้งานได้ เราตรวจสอบจำนวนสคริปต์ในไดเร็กทอรี จากนั้นรันสคริปต์

 ลส
 ./script.sh 

การรัน script.sh script

โฆษณา

Bash เกิดข้อผิดพลาด เราลบไฟล์สคริปต์ทั้งหมดยกเว้นไฟล์เดียวและเรียกใช้สคริปต์อีกครั้ง

 ลส
 ./script.sh 

การรันสคริปต์ script.sh ด้วยสคริปต์เดียวในไดเร็กทอรี

การทดสอบตามเงื่อนไขคืนค่าเป็น true และสคริปต์ไม่ทำให้เกิดข้อผิดพลาด การแก้ไขสคริปต์เพื่อใช้วงเล็บคู่ทำให้เกิดการทำงานประเภทที่สาม

 #!/bin/bash

ถ้า [[ -a *.sh ]];
แล้ว
  echo "พบไฟล์สคริปต์"
อื่น
  echo "ไม่พบไฟล์สคริปต์"
fi

เราบันทึกสิ่งนี้ลงในไฟล์ชื่อ “dscript.sh” และทำให้สามารถเรียกใช้งานได้ การเรียกใช้สคริปต์นี้ในไดเร็กทอรีที่มีสคริปต์จำนวนมากไม่มีข้อผิดพลาด แต่สคริปต์ไม่รู้จักไฟล์สคริปต์ใดๆ

คำสั่งแบบมีเงื่อนไขโดยใช้วงเล็บคู่จะแก้ไขเฉพาะค่า true ในกรณีที่คุณมีไฟล์ชื่อ “*.sh” ในไดเร็กทอรี

 ./dscript.sh 

การรันสคริปต์ dscript.sh

ตรรกะ AND และ OR

วงเล็บคู่ให้คุณใช้ && และ || เป็นโอเปอเรเตอร์ตรรกะ AND และ OR

สคริปต์นี้ควรแก้ไขข้อความสั่งตามเงื่อนไขเป็นจริงเพราะ 10 มีค่าเท่ากับ 10 และ 25 น้อยกว่า 26

 #!/bin/bash

แรก=10
วินาที=25

ถ้า [[ แรก -eq 10 && วินาที -lt 26 ]];
แล้ว
  echo "ตรงตามเงื่อนไข"
อื่น
  echo "เงื่อนไขล้มเหลว"
fi
โฆษณา

บันทึกข้อความนี้ลงในไฟล์ชื่อ "and.sh" ทำให้ใช้งานได้ และเรียกใช้ด้วย:

 ./และ.sh 

การรันสคริปต์ and.sh

สคริปต์ทำงานตามที่เราคาดหวัง

คราวนี้เราจะใช้ || โอเปอเรเตอร์ คำสั่งแบบมีเงื่อนไขควรแก้ไขเป็นจริงเพราะแม้ว่า 10 จะไม่เกิน 15 แต่ 25 ยังน้อยกว่า 26 ตราบใดที่การเปรียบเทียบครั้งแรก หรือ การเปรียบเทียบครั้งที่สองเป็นจริง คำสั่งแบบมีเงื่อนไขทั้งหมดจะแก้ไขเป็นจริง

บันทึกข้อความนี้เป็น "or.sh" และทำให้ใช้งานได้

 #!/bin/bash

แรก=10
วินาที=25

ถ้า [[ แรก -gt 15 || วินาที -lt 26 ]];
แล้ว
  echo "ตรงตามเงื่อนไข"
อื่น
  echo "เงื่อนไขล้มเหลว"
fi
 ./or.sh 

การรันสคริปต์ or.sh

Regexes

คำสั่งแบบมีเงื่อนไขวงเล็บคู่อนุญาตให้ใช้ตัวดำเนินการ =~ ซึ่งใช้รูปแบบการค้นหา regex ในสตริงกับอีกครึ่งหนึ่งของคำสั่ง หาก regex เป็นที่พอใจ คำสั่งแบบมีเงื่อนไขจะถือว่าเป็นจริง หาก regex พบว่าไม่ตรงกับคำสั่งเงื่อนไขจะแก้ไขเป็นเท็จ

ที่เกี่ยวข้อง: วิธีใช้นิพจน์ทั่วไป (regexes) บน Linux

บันทึกข้อความนี้ลงในไฟล์ชื่อ “regex.sh” และทำให้ใช้งานได้

 #!/bin/bash

คำ = "หนึ่งสองสาม"
WordsandNumbers="หนึ่ง 1 สอง 2 สาม 3"
email="[email protected]"

หน้ากาก1="[0-9]"
mask2="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}"

ถ้า [[ $words =~ $mask1 ]];
แล้ว
  echo "\"$words\" มีตัวเลข"
อื่น
  echo "ไม่พบตัวเลขใน \"$words\""
fi

ถ้า [[ $WordsandNumbers =~ $mask1 ]];
แล้ว
  echo "\"$WordsandNumbers\" มีตัวเลข"
อื่น
  echo "ไม่พบตัวเลขใน \"$WordsandNumbers\""
fi

ถ้า [[ $email =~ $mask2 ]];
แล้ว
  echo "\"$email\" เป็นที่อยู่อีเมลที่ถูกต้อง"
อื่น
  echo "ไม่สามารถแยกวิเคราะห์ \"$email\""
fi

วงเล็บคู่ชุดแรกใช้ตัวแปรสตริง $mask1 เป็น regex ซึ่งมีรูปแบบสำหรับตัวเลขทั้งหมดในช่วงศูนย์ถึงเก้า ใช้ regex นี้กับตัวแปรสตริง $words

วงเล็บคู่ชุดที่สองใช้ตัวแปรสตริง $mask1 เป็น regex อีกครั้ง แต่คราวนี้ใช้กับตัวแปรสตริง $WordsandNumbers

โฆษณา

วงเล็บคู่ชุดสุดท้ายใช้มาสก์ regex ที่ซับซ้อนมากขึ้นในตัวแปรสตริง $mask2

  • [A-Za-z0-9._%+-]+ : ตรงกับอักขระที่เป็นอักษรตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก หรือตัวเลขใดๆ ตั้งแต่ศูนย์ถึงเก้า หรือจุด ขีดล่าง เครื่องหมายเปอร์เซ็นต์ หรือเครื่องหมายบวกหรือลบ . เครื่องหมาย “ + ” ด้านนอกของ “ [] ” หมายถึงการจับคู่ซ้ำสำหรับอักขระจำนวนมากเท่าที่พบ
  • @ : ตรงกับอักขระ “@” เท่านั้น
  • [A-Za-z0-9.-]+ : ใช้กับอักขระที่เป็นอักษรตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก หรือตัวเลขตั้งแต่ศูนย์ถึงเก้า หรือจุดหรือขีดกลาง เครื่องหมาย “ + ” ด้านนอกของ “ [ ] ” หมายถึงการจับคู่ซ้ำสำหรับอักขระจำนวนมากเท่าที่พบ
  • . : สิ่งนี้ตรงกับ “.” ตัวอักษรเท่านั้น
  • [A-Za-z]{2,4} : ตรงกับอักษรตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก “ {2,4} ” หมายถึงจับคู่อักขระอย่างน้อยสองตัวและไม่เกินสี่ตัว

เมื่อนำทั้งหมดมารวมกันแล้ว regex mask จะตรวจสอบว่าที่อยู่อีเมลมีรูปแบบถูกต้องหรือไม่

บันทึกข้อความสคริปต์ลงในไฟล์ชื่อ “regex.sh” และทำให้สามารถเรียกใช้งานได้ เมื่อเรารันสคริปต์ เราจะได้ผลลัพธ์นี้

 ./regex.sh 

การรันสคริปต์ regex.sh

คำสั่งเงื่อนไขแรกล้มเหลวเนื่องจาก regex กำลังมองหาตัวเลข แต่ไม่มีตัวเลขในค่าที่เก็บไว้ในตัวแปรสตริง $words

คำสั่งเงื่อนไขที่สองสำเร็จเนื่องจากตัวแปรสตริง $WordsandNumbers มีตัวเลข

โฆษณา

คำสั่งเงื่อนไขขั้นสุดท้ายสำเร็จ กล่าวคือ แก้ไขให้เป็นจริง เนื่องจากที่อยู่อีเมลมีรูปแบบที่เหมาะสม

เงื่อนไขเดียวเท่านั้น

การทดสอบแบบมีเงื่อนไขแบบวงเล็บคู่ช่วยให้สคริปต์ของคุณมีความยืดหยุ่นและอ่านง่าย เพียงแค่ใช้ regexes ในการทดสอบแบบมีเงื่อนไขของคุณ ก็ทำให้เรียนรู้วิธีใช้ [[ และ ]] ได้

เพียงตรวจสอบให้แน่ใจว่าสคริปต์เรียกใช้เชลล์ที่รองรับเช่น Bash

ที่เกี่ยวข้อง: 15 ตัวละครพิเศษที่คุณต้องรู้สำหรับ Bash