ฉันสับสนเล็กน้อยเกี่ยวกับสิ่งที่ตัวดำเนินการเหล่านี้ทำแตกต่างกันเมื่อใช้ในการทุบตี
[[ , [ , ( , ((
ฉันเคยเห็นคนใช้พวกเขาถ้างบเช่นนี้:
if [[condition]]
if [condition]
if ((condition))
if (condition)
ฉันสับสนเล็กน้อยเกี่ยวกับสิ่งที่ตัวดำเนินการเหล่านี้ทำแตกต่างกันเมื่อใช้ในการทุบตี
[[ , [ , ( , ((
ฉันเคยเห็นคนใช้พวกเขาถ้างบเช่นนี้:
if [[condition]]
if [condition]
if ((condition))
if (condition)
คำตอบ:
if
คำสั่งมักจะมีลักษณะเหมือน
if commands1
then
commands2
else
commands3
fi
ส่วนthen
คำสั่งจะถูกดำเนินการถ้ารหัสทางออกของcommands1
เป็นศูนย์ หากรหัสทางออกไม่ใช่ศูนย์ดังนั้นelse
ประโยคจะถูกดำเนินการ commands1
สามารถเรียบง่ายหรือซับซ้อน มันสามารถยกตัวอย่างเช่นเป็นลำดับหนึ่งหรือมากกว่าท่อแยกจากกันโดยหนึ่งในผู้ประกอบการ;
, &
, หรือ&&
เงื่อนไขที่แสดงด้านล่างนี้มีเพียงกรณีพิเศษ:||
if
commands1
if [ condition ]
นี่คือtest
คำสั่งเชลล์แบบดั้งเดิม มันมีอยู่ในเปลือก POSIX ทั้งหมด คำสั่งทดสอบตั้งรหัสการออกและif
คำสั่งที่ทำหน้าที่ตาม การทดสอบโดยทั่วไปคือว่ามีไฟล์อยู่หรือมีหนึ่งหมายเลขเท่ากับจำนวนอื่น
if [[ condition ]]
นี่เป็นรูปแบบที่อัปเกรดใหม่test
จากkshซึ่งbashและzshรองรับเช่นกัน นี้test
คำสั่งนอกจากนี้ยังกำหนดรหัสทางออกและif
คำสั่งที่ทำหน้าที่ตาม ในบรรดาคุณสมบัติเพิ่มเติมมันสามารถทดสอบว่าสตริงนั้นตรงกับนิพจน์ทั่วไปหรือไม่
if ((condition))
ส่วนขยายkshอื่นที่bashและzshรองรับเช่นกัน สิ่งนี้ดำเนินการทางคณิตศาสตร์ เนื่องจากผลลัพธ์ของเลขคณิตรหัสออกจะถูกตั้งค่าและif
คำสั่งจะทำงานตามนั้น มันจะส่งกลับรหัสทางออกของศูนย์ (จริง) ถ้าผลลัพธ์ของการคำนวณทางคณิตศาสตร์เป็นศูนย์ ชอบ[[...]]
ฟอร์มนี้ไม่ใช่ POSIX และไม่ใช่พกพา
if (command)
คำสั่งนี้รันคำสั่งในเชลล์ย่อย เมื่อคำสั่งเสร็จสมบูรณ์มันจะตั้งรหัสออกและif
คำสั่งจะทำงานตามนั้น
เหตุผลทั่วไปสำหรับการใช้ subshell เช่นนี้คือการ จำกัด ผลข้างเคียงของcommand
ถ้าcommand
จำเป็นต้องมีการกำหนดตัวแปรหรือการเปลี่ยนแปลงอื่น ๆ เพื่อสภาพแวดล้อมของเปลือก การเปลี่ยนแปลงดังกล่าวจะไม่คงอยู่หลังจากที่ subshell เสร็จสมบูรณ์
if command
คำสั่งจะถูกดำเนินการและif
คำสั่งทำหน้าที่ตามรหัสออก
[
จริง ๆ แล้วเป็นไบนารีไม่ใช่คำสั่งหรือสัญลักษณ์ภายใน /bin
โดยทั่วไปอาศัยอยู่ใน
[
test
มีรุ่นไบนารีสำหรับเหตุผลด้านความเข้ากันได้ ตรวจสอบและhelp [
help test
$((
เช่นการขยายเลขคณิตคือและมันง่ายที่จะทำให้สับสน) บ่อยครั้งวิธีแก้ปัญหาคือการใช้สิ่งที่ต้องการ[ $((2+2)) -eq 4 ]
ใช้ประโยชน์จากเลขคณิตในงบสรุป
(…)
วงเล็บบ่งชี้subshell สิ่งที่อยู่ข้างในนั้นไม่ได้แสดงออกในภาษาอื่น ๆ อีกมากมาย มันเป็นรายการคำสั่ง (เช่นเดียวกับวงเล็บนอก) คำสั่งเหล่านี้จะถูกดำเนินการในกระบวนการย่อยที่แยกต่างหากดังนั้นการเปลี่ยนเส้นทางการกำหนด ฯลฯ ที่ดำเนินการภายในวงเล็บจะไม่มีผลใด ๆ นอกวงเล็บ
$(…)
คือการทดแทนคำสั่ง : มีคำสั่งอยู่ในวงเล็บและใช้เอาต์พุตจากคำสั่งเป็นส่วนหนึ่งของบรรทัดคำสั่ง (หลังจากการขยายเพิ่มเติมยกเว้นการทดแทนอยู่ระหว่างเครื่องหมายคำพูดคู่ แต่เป็นอีกเรื่องหนึ่ง ) .{ … }
การจัดฟันเป็นเหมือนเครื่องหมายวงเล็บในการที่พวกเขาจัดกลุ่มคำสั่ง แต่พวกเขามีอิทธิพลเฉพาะกับการแยกวิเคราะห์ โปรแกรมที่x=2; { x=4; }; echo $x
พิมพ์ 4 ในขณะที่x=2; (x=4); echo $x
พิมพ์ 2 (เช่นวงเล็บเป็นคำหลักจะต้องมีการคั่นและพบในตำแหน่งคำสั่ง (ดังนั้นช่องว่างหลัง{
และ;
ก่อน}
) ในขณะที่วงเล็บไม่. นั่นเป็นเพียงการเล่นโวหารไวยากรณ์)
${VAR}
เป็นการขยายพารามิเตอร์ซึ่งขยายไปถึงมูลค่าของตัวแปรโดยมีการแปลงพิเศษ ksh93
เปลือกยังสนับสนุน${ cmd;}
เป็นรูปแบบของการทดแทนคำสั่งที่ไม่วางไข่ subshell((…))
วงเล็บคู่ล้อมรอบคำสั่งทางคณิตศาสตร์นั่นคือการคำนวณบนจำนวนเต็มด้วยไวยากรณ์ที่คล้ายกับภาษาการเขียนโปรแกรมอื่น ๆ ไวยากรณ์นี้ส่วนใหญ่จะใช้สำหรับการมอบหมายและในเงื่อนไข มีอยู่ใน ksh / bash / zsh เท่านั้นไม่ใช่ sh แบบธรรมดา
$((…))
ซึ่งขยายเป็นค่าจำนวนเต็มของนิพจน์[ … ]
วงเล็บเดียวล้อมรอบนิพจน์เงื่อนไข นิพจน์ตามเงื่อนไขส่วนใหญ่จะสร้างจากตัวดำเนินการเช่น-n "$variable"
เพื่อทดสอบว่าตัวแปรว่างเปล่าหรือไม่และ-e "$file"
เพื่อทดสอบว่ามีไฟล์อยู่หรือไม่ โปรดทราบว่าคุณต้องการช่องว่างรอบตัวดำเนินการแต่ละตัว (เช่น[ "$x" = "$y" ]
ไม่ใช่[ "$x"="$y" ]
;
ทั้งด้านในและด้านนอกวงเล็บ (เช่น[ -n "$foo" ]
ไม่ใช่[-n "$foo"]
[[ … ]]
วงเล็บคู่เป็นรูปแบบทางเลือกของนิพจน์เงื่อนไขใน ksh / bash / zsh ด้วยคุณสมบัติเพิ่มเติมบางอย่างเช่นคุณสามารถเขียน[[ -L $file && -f $file ]]
เพื่อทดสอบว่าไฟล์นั้นเป็นลิงก์สัญลักษณ์ไปยังไฟล์ปกติหรือ[ -L "$file" ] && [ -f "$file" ]
ไม่ ดูทำไมการขยายพารามิเตอร์ด้วยช่องว่างโดยไม่มีเครื่องหมายคำพูดทำงานในวงเล็บใหญ่คู่ [[แต่ไม่ใช่วงเล็บปีกกาเดียว [? สำหรับเพิ่มเติมในหัวข้อนี้ในเชลล์คำสั่งทุกคำสั่งเป็นคำสั่งแบบมีเงื่อนไข: คำสั่งทุกคำสั่งมีสถานะการส่งคืนซึ่งเป็น 0 บ่งชี้ถึงความสำเร็จหรือจำนวนเต็มระหว่าง 1 ถึง 255 (และอาจมากขึ้นในบางเชลล์) บ่งชี้ความล้มเหลว [ … ]
คำสั่ง (หรือ[[ … ]]
รูปแบบไวยากรณ์) เป็นคำสั่งโดยเฉพาะอย่างยิ่งซึ่งยังสามารถสะกดtest …
และประสบความสำเร็จเมื่อไฟล์ที่มีอยู่หรือเมื่อสตริงเป็นไม่ว่างเปล่าหรือเป็นจำนวนมากเมื่อมีขนาดเล็กกว่าที่อื่น ฯลฯ((…))
รูปแบบไวยากรณ์ประสบความสำเร็จเมื่อจำนวน ไม่ใช่ศูนย์ นี่เป็นตัวอย่างของเงื่อนไขในเชลล์สคริปต์:
ทดสอบว่าmyfile
มีสตริงหรือไม่hello
:
if grep -q hello myfile; then …
หากmydir
เป็นไดเรกทอรีให้เปลี่ยนเป็นและทำสิ่งต่างๆ:
if cd mydir; then
echo "Creating mydir/myfile"
echo 'some content' >myfile
else
echo >&2 "Fatal error. This script requires mydir to exist."
fi
ทดสอบว่ามีไฟล์ชื่อmyfile
ในไดเรกทอรีปัจจุบันหรือไม่:
if [ -e myfile ]; then …
เหมือนกัน แต่ยังรวมถึงลิงค์สัญลักษณ์ห้อยต่องแต่ง:
if [ -e myfile ] || [ -L myfile ]; then …
ทดสอบว่าค่าของx
(ซึ่งสันนิษฐานว่าเป็นตัวเลข) อย่างน้อย 2 หรือสามารถพกพาได้:
if [ "$x" -ge 2 ]; then …
ทดสอบว่าค่าของx
(ซึ่งสันนิษฐานว่าเป็นตัวเลข) อย่างน้อย 2 ใน bash / ksh / zsh:
if ((x >= 2)); then …
-a
แทน&&
ดังนั้นหนึ่งสามารถเขียน: [ -L $file -a -f $file ]
ซึ่งเป็นจำนวนอักขระที่เหมือนกันภายในวงเล็บโดยไม่ต้องเพิ่ม[
และ]
...
-a
และ-o
มีปัญหาเพราะสามารถแยกวิเคราะห์ได้ไม่ถูกต้องหากตัวถูกดำเนินการบางตัวที่เกี่ยวข้องดูเหมือนตัวดำเนินการ นั่นเป็นเหตุผลที่ฉันไม่พูดถึงพวกเขา: พวกเขาไม่มีประโยชน์และไม่ได้ผลเสมอไป และไม่เคยเขียนการขยายตัวแปรที่ไม่มีคำที่ไม่มีเหตุผลที่ดี: ใช้ได้[[ -L $file -a -f $file ]]
แต่มีวงเล็บเดียวที่คุณต้องการ[ -L "$file" -a -f "$file" ]
(ซึ่งก็โอเคเช่นถ้า$file
เริ่มต้นด้วย/
หรือเสมอ./
)
[[ -L $file && -f $file ]]
(ไม่มี-a
กับ[[...]]
ตัวแปร)
จากเอกสาร bash :
(list)
รายการจะถูกดำเนินการในสภาพแวดล้อมของ subshell (ดูคำสั่งการดำเนินการด้านสิ่งแวดล้อมด้านล่าง) การกำหนดตัวแปรและคำสั่ง builtin ที่ส่งผลกระทบต่อสภาพแวดล้อมของเชลล์จะไม่มีผลบังคับใช้หลังจากคำสั่งเสร็จสิ้น สถานะการส่งคืนคือสถานะการออกของรายการ
ในคำอื่น ๆ ที่คุณให้แน่ใจว่าสิ่งที่เกิดขึ้นในรายการ '(เช่นcd
) ไม่มีผลนอกและ(
)
สิ่งเดียวที่จะรั่วไหลเป็นรหัสทางออกของคำสั่งสุดท้ายหรือมีset -e
คำสั่งแรกที่สร้างข้อผิดพลาด (นอกเหนือจากไม่กี่เช่นif
, while
ฯลฯ )
((expression))
นิพจน์ได้รับการประเมินตามกฎที่อธิบายไว้ด้านล่างภายใต้การประเมิน ARITHMETIC หากค่าของนิพจน์ไม่ใช่ศูนย์สถานะการส่งคืนจะเป็น 0 มิฉะนั้นสถานะการส่งคืนคือ 1 ซึ่งเทียบเท่ากับให้ "expression"
นี่คือส่วนขยายทุบตีช่วยให้คุณสามารถทำคณิตศาสตร์ สิ่งนี้ค่อนข้างคล้ายกับการใช้expr
โดยไม่มีข้อ จำกัด ทั้งหมดexpr
(เช่นมีช่องว่างทุกหนทุกแห่งการหลบหนี*
ฯลฯ )
[[ expression ]]
ส่งคืนสถานะ 0 หรือ 1 ขึ้นอยู่กับการประเมินผลของนิพจน์เงื่อนไขแบบนิพจน์ การแสดงออกประกอบด้วยกลุ่มที่อธิบายไว้ด้านล่างภายใต้การแสดงออกตามเงื่อนไข การแยกคำและการขยายชื่อพา ธ จะไม่ดำเนินการกับคำระหว่าง [[และ]]; การขยายตัวตัวหนอนพารามิเตอร์และการขยายตัวแปรการขยายเลขคณิตการทดแทนคำสั่งการทดแทนกระบวนการและการลบเครื่องหมายถูกดำเนินการ ตัวดำเนินการแบบมีเงื่อนไขเช่น -f ต้องไม่ถูกยกให้เป็นที่รู้จักเมื่อใช้กับ [[ตัวดำเนินการ <และ> จะเรียงลำดับพจนานุกรมโดยใช้ภาษาปัจจุบัน
นี่เป็นการทดสอบขั้นสูงเพื่อเปรียบเทียบสตริงตัวเลขและไฟล์เช่นtest
ข้อเสนอ แต่มีประสิทธิภาพยิ่งขึ้น
[ expr ]
ส่งคืนสถานะ 0 (จริง) หรือ 1 (false) ขึ้นอยู่กับการประเมินผลของนิพจน์เงื่อนไขแบบ expr แต่ละโอเปอเรเตอร์และโอเปอเรเตอร์และต้องเป็นอาร์กิวเมนต์ที่แยกต่างหาก การแสดงออกประกอบด้วยพรรคที่อธิบายไว้ข้างต้นภายใต้การแสดงออกตามเงื่อนไข การทดสอบไม่ยอมรับตัวเลือกใด ๆ และไม่ยอมรับและเพิกเฉยต่อข้อโต้แย้งของ - เป็นการบ่งบอกถึงจุดสิ้นสุดของตัวเลือก[ ... ]
สิ่งนี้เรียกtest
ว่า ที่จริงในวันเก่า[
เป็น symbolic link test
ไป มันทำงานในลักษณะเดียวกันและคุณมีข้อ จำกัด เหมือนกัน ]
ตั้งแต่ไบนารีรู้ชื่อด้วยซึ่งจะได้รับการเริ่มต้นโปรแกรมการทดสอบสามารถแยกพารามิเตอร์จนกว่าจะพบพารามิเตอร์ เทคนิค Unix สนุก
โปรดทราบว่าในกรณีของbash
, [
และtest
มีฟังก์ชั่น (ตามที่กล่าวไว้ในความคิดเห็น) ยังสวยมากข้อ จำกัด เดียวกันกับ
test
และ[
เป็นคำสั่งในตัวใน Bash แต่เป็นไปได้ว่ามีไบนารีภายนอกอยู่ด้วย
[
ไม่ใช่ลิงก์สัญลักษณ์ไปยังtest
ระบบที่ทันสมัยที่สุด
strings /usr/bin/test
แสดงว่ามันมีข้อความช่วยเหลือด้วยดังนั้นฉันไม่รู้ว่าจะพูดอะไร
test
คำสั่งนั้นจำเป็นต้องมีอยู่อย่างชัดเจนว่าเป็นคำสั่งที่ยึดตามไฟล์แบบสแตนด์อโลนโดยมาตรฐาน แต่ก็ไม่มีอะไรที่ระบุว่า[
จำเป็นต้องมีการใช้งานชุดตัวเลือกด้วยเช่นกัน ตัวอย่างเช่น Solaris 11 ไม่ได้ให้การ[
ปฏิบัติการใด ๆแต่ก็เป็นไปตามมาตรฐาน POSIX อย่างสมบูรณ์
[
VS [[
คำตอบนี้จะครอบคลุม[
VS [[
ย่อยของคำถาม
ความแตกต่างบางประการใน Bash 4.3.11:
POSIX vs Bash extension:
[
POSIX คือ[[
เป็นส่วนขยายของBash¹ที่: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsคำสั่งปกติกับเวทมนตร์
[
เป็นเพียงคำสั่งปกติที่มีชื่อแปลก ๆ
]
เป็นเพียงข้อโต้แย้ง[
ที่ป้องกันไม่ให้มีการใช้ข้อโต้แย้งเพิ่มเติม
จริง ๆ แล้ว Ubuntu 16.04 มีไฟล์ปฏิบัติการที่/usr/bin/[
ให้มาโดย coreutils แต่เวอร์ชั่นในตัวของ bash นั้นมีความสำคัญกว่า
ไม่มีการเปลี่ยนแปลงในวิธีที่ Bash วิเคราะห์คำสั่ง
โดยเฉพาะอย่างยิ่ง<
คือการเปลี่ยนเส้นทาง&&
และ||
เชื่อมคำสั่งหลาย ๆ คำสั่ง( )
สร้าง subshells เว้นแต่จะหลบหนีไป\
และการขยายคำจะเกิดขึ้นตามปกติ
[[ X ]]
เป็นโครงสร้างเดียวที่ทำให้การX
แยกวิเคราะห์อย่างน่าอัศจรรย์ <
, &&
, ||
และ()
ได้รับการปฏิบัติเป็นพิเศษและกฎการแยกคำที่แตกต่างกัน
นอกจากนี้ยังมีความแตกต่างต่อไปเหมือนและ=
=~
ใน Bashese: [
เป็นคำสั่งในตัวและ[[
เป็นคำหลัก: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: การเปรียบเทียบพจนานุกรม[ a \< b ]
: เหมือนด้านบน \
จำเป็นหรือไม่ก็เปลี่ยนเส้นทางเหมือนสำหรับคำสั่งอื่น ๆ นามสกุลทุบตีexpr a \< b > /dev/null
: POSIX เทียบเท่า²ดู: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
และ ||
[[ a = a && b = b ]]
: จริงตรรกะและ[ a = a && b = b ]
: ข้อผิดพลาดทางไวยากรณ์&&
แยกวิเคราะห์เป็นตัวคั่นคำสั่ง ANDcmd1 && cmd2
[ a = a -a b = b ]
: เทียบเท่า แต่เลิกใช้แล้วโดยPOSIX³[ a = a ] && [ b = b ]
: POSIX และเทียบเท่าที่เชื่อถือได้(
[[ (a = a || a = b) && a = b ]]
: false[ ( a = a ) ]
: ข้อผิดพลาดทางไวยากรณ์()
ถูกตีความว่าเป็น subshell[ \( a = a -o a = b \) -a a = b ]
: เทียบเท่า แต่()
เลิกใช้แล้วโดย POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX เทียบเท่า5การแยกคำและการสร้างชื่อไฟล์ตามการขยาย (แยก + glob)
x='a b'; [[ $x = 'a b' ]]
: จริงไม่จำเป็นต้องใส่เครื่องหมายคำพูดx='a b'; [ $x = 'a b' ]
: ข้อผิดพลาดทางไวยากรณ์ขยายเป็น [ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: ข้อผิดพลาดทางไวยากรณ์หากมีมากกว่าหนึ่งไฟล์ในไดเรกทอรีปัจจุบันx='a b'; [ "$x" = 'a b' ]
: เทียบเท่า POSIX=
[[ ab = a? ]]
: จริงเพราะมันจับคู่รูปแบบ (* ? [
เป็นเวทย์มนตร์) ห้าม glob ขยายไฟล์ในไดเรกทอรีปัจจุบัน[ ab = a? ]
: a?
glob ขยายตัว ดังนั้นอาจเป็นจริงหรือเท็จขึ้นอยู่กับไฟล์ในไดเรกทอรีปัจจุบัน[ ab = a\? ]
: เท็จไม่ใช่การขยาย glob=
และ==
เหมือนกันทั้งใน[
และ[[
, แต่==
เป็นส่วนขยายของ Bashcase ab in (a?) echo match; esac
: เทียบเท่า POSIX[[ ab =~ 'ab?' ]]
: false 4 , สูญเสียเวทย์ด้วย''
[[ ab? =~ 'ab?' ]]
: จริง=~
[[ ab =~ ab? ]]
: จริง POSIX ขยายการจับคู่การแสดงออกปกติ?
ไม่ได้ขยาย[ a =~ a ]
: ข้อผิดพลาดทางไวยากรณ์ ไม่เทียบเท่าทุบตีprintf 'ab\n' | grep -Eq 'ab?'
: เทียบเท่า POSIX (ข้อมูลบรรทัดเดียวเท่านั้น)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: เทียบเท่า POSIXคำแนะนำ : []
มักจะใช้
มี POSIX ที่เทียบเท่าสำหรับการ[[ ]]
สร้างทุกครั้งที่ฉันเห็น
ถ้าคุณใช้[[ ]]
คุณ:
[
เป็นเพียงคำสั่งปกติที่มีชื่อแปลก ๆ ไม่มีความหมายพิเศษเกี่ยวข้อง¹แรงบันดาลใจจากสิ่ง[[...]]
ก่อสร้างที่เทียบเท่าใน Korn เชลล์
² แต่ล้มเหลวสำหรับบางค่าของa
หรือb
(เช่น+
หรือindex
) และทำการเปรียบเทียบตัวเลขถ้าa
และb
ดูเหมือนเลขจำนวนเต็มฐานสิบ expr "x$a" '<' "x$b"
ทำงานได้ทั้งสองอย่าง
³และยังล้มเหลวสำหรับค่าของบางส่วนa
หรือb
เหมือนหรือ!
(
4ใน bash 3.2 ขึ้นไปและไม่สามารถเปิดใช้งานความเข้ากันได้กับ bash 3.1 (เช่นเดียวกับBASH_COMPAT=3.1
)
5แม้ว่าการจัดกลุ่ม (ที่นี่พร้อมกับ{...;}
กลุ่มคำสั่งแทนที่จะเป็นกลุ่ม(...)
ย่อยที่ไม่จำเป็น) ไม่จำเป็นเนื่องจากตัวดำเนินการ||
และ&&
เชลล์ (ตรงข้ามกับตัวดำเนินการ||
และ&&
[[...]]
ตัวดำเนินการหรือ-o
/ -a
[
ตัวดำเนินการ/ ) มีลำดับความสำคัญเท่ากัน ดังนั้น[ a = a ] || [ a = b ] && [ a = b ]
จะเทียบเท่า
expr
คำตอบแล้ว คำว่า "Bash extension" ไม่ได้หมายความว่า Bash เป็นเชลล์ตัวแรกที่เพิ่มไวยากรณ์การเรียนรู้ POSIX sh กับ Bash นั้นเพียงพอแล้วที่จะทำให้ฉันบ้า
man test
ว่าคุณพยายามman [
และหลงทาง ที่จะอธิบายตัวแปร POSIX
ตัวอย่างบางส่วน:
การทดสอบแบบดั้งเดิม:
foo="some thing"
# check if value of foo is not empty
if [ -n "$foo" ] ; then...
if test -n "$foo" ; then...
test
และ[
เป็นคำสั่งเหมือนคนอื่น ๆ ดังนั้นตัวแปรจึงแบ่งออกเป็นคำต่าง ๆ เว้นแต่ว่าจะอยู่ในเครื่องหมายคำพูด
การทดสอบรูปแบบใหม่
[[ ... ]]
เป็นโครงสร้างเชลล์พิเศษ (ใหม่กว่า) ซึ่งทำงานแตกต่างกันเล็กน้อยสิ่งที่ชัดเจนที่สุดคือการที่มันไม่ได้ใช้ตัวแปรแบ่งคำ
if [[ -n $foo ]] ; then...
บางเอกสารเกี่ยวกับ[
และ[[
ที่นี่
การทดสอบทางคณิตศาสตร์:
foo=12 bar=3
if (( $foo + $bar == 15 )) ; then ...
คำสั่ง "ปกติ":
ทั้งหมดข้างต้นทำหน้าที่เหมือนคำสั่งปกติและif
สามารถใช้คำสั่งใด ๆ :
# grep returns true if it finds something
if grep pattern file ; then ...
หลายคำสั่ง:
หรือเราสามารถใช้หลายคำสั่ง การห่อชุดคำสั่งในการ( ... )
รันคำสั่งในเชลล์ย่อยสร้างสำเนาชั่วคราวของสถานะเชลล์ (ไดเร็กทอรีการทำงานตัวแปร) หากเราจำเป็นต้องเรียกใช้โปรแกรมบางโปรแกรมชั่วคราวในไดเรกทอรีอื่น:
# this will move to $somedir only for the duration of the subshell
if ( cd $somedir ; some_test ) ; then ...
# while here, the rest of the script will see the new working
# directory, even after the test
if cd $somedir ; some_test ; then ...
Bash มีสองวิธีในการจัดกลุ่มรายการคำสั่งที่จะดำเนินการเป็นหน่วย
( list )
การวางรายการคำสั่งระหว่างวงเล็บทำให้เกิดสภาวะแวดล้อม subshell ที่จะสร้างและแต่ละคำสั่งในรายการที่จะดำเนินการใน subshell นั้น เนื่องจากรายการจะถูกดำเนินการใน subshell การกำหนดตัวแปรจึงยังคงมีผลหลังจาก subshell เสร็จสมบูรณ์
$ a=1; (a=2; echo "inside: a=$a"); echo "outside: a=$a"
inside: a=2
outside: a=1
{ list; }
วางรายการของคำสั่งระหว่างวงเล็บปีกกาทำให้เกิดรายการที่จะดำเนินการในบริบทเปลือกปัจจุบัน ไม่มีการสร้างเชลล์ย่อย จำเป็นต้องใช้รายการอัฒภาค (หรือขึ้นบรรทัดใหม่) แหล่ง
${} Parameter expansion Ex: ANIMAL=duck; echo One $ANIMAL, two ${ANIMAL}s
$() Command substitution Ex: result=$(COMMAND)
$(()) Arithmetic expansion Ex: var=$(( 20 + 5 ))
คร่อมเดี่ยวเช่น[]
สำหรับการเปรียบเทียบ==, !=, <,
และ>
และควรใช้และสำหรับการเปรียบเทียบเชิงตัวเลขeq, ne,lt
และgt
ควรใช้
ตัวยึดเสริมเช่น[[]]
ในตัวอย่างข้างต้นทั้งหมดเราใช้วงเล็บเดียวเท่านั้นเพื่อล้อมรอบนิพจน์เงื่อนไข แต่ bash อนุญาตให้วงเล็บคู่ซึ่งทำหน้าที่เป็นรุ่นปรับปรุงของไวยากรณ์วงเล็บเดี่ยว
สำหรับการเปรียบเทียบ==, !=, <,
และ>
สามารถใช้งานได้อย่างแท้จริง
[
เป็นคำพ้องสำหรับคำสั่งทดสอบ แม้ว่ามันจะถูกสร้างไว้ในเชลล์มันจะสร้างกระบวนการใหม่[[
เป็นรุ่นที่ปรับปรุงใหม่ของมันซึ่งเป็นคำหลักไม่ใช่โปรแกรม[[
เป็นที่เข้าใจกันโดยและKorn
Bash