ไม่มีที่สิ้นสุดในขณะที่วนซ้ำในสคริปต์ BASH BASH: คำอธิบายของ for, while, until loops และตัวอย่างการใช้งาน ตัวอย่าง: การค้นหาไฟล์ปฏิบัติการ
ผู้เขียน : พอล คอบเบาต์
วันที่เผยแพร่: 16 ตุลาคม 2014
แปล: อ. ภานิน
วันที่แปล: 21 ธันวาคม 2014
บทที่ 22 วนซ้ำในสคริปต์
คำสั่งทดสอบ
คำสั่ง test ช่วยให้คุณกำหนดได้ว่านิพจน์เป็นจริงหรือเท็จ เริ่มต้นด้วยการทดสอบว่าค่าจำนวนเต็ม 10 มากกว่าค่าจำนวนเต็ม 55 หรือไม่ $ test 10 -gt 55 ; สะท้อน $? 1$
คำสั่ง test จะส่งคืน 1 หากนิพจน์เป็นเท็จ และดังที่คุณจะเห็นในตัวอย่างต่อไปนี้ คำสั่ง test จะส่งคืนค่า 0 หากนิพจน์ประเมินว่าเป็นจริง $ ทดสอบ 56 -gt 55 ; สะท้อน $? $0
หากคุณสะดวกกว่าที่จะทำงานกับสตริงจริงและเท็จ คุณสามารถใช้คำสั่ง test ดังที่แสดงด้านล่าง $ ทดสอบ 56 -gt 55 && เสียงสะท้อนจริง || echo false true $ ทดสอบ 6 -gt 55 && echo true || สะท้อนเท็จเท็จ
คำสั่งทดสอบยังสามารถแทนที่ด้วยวงเล็บเหลี่ยมได้ ดังนั้นคำสั่งในตัวอย่างด้านล่างจึงเหมือนกับคำสั่งในตัวอย่างด้านบนทุกประการ $ [ 56 -gt 55 ] && สะท้อนจริง || echo false จริง $ [ 6 -gt 55 ] && echo true || สะท้อนเท็จเท็จ
ด้านล่างนี้เป็นตัวอย่างการใช้งานเช็คบางรายการ อ้างถึงหน้าทดสอบคนเพื่อดูภาพรวมของ คุณลักษณะเพิ่มเติมการดำเนินการตรวจสอบต่างๆ [ -d foo ] มีไดเร็กทอรี foo หรือไม่? [ -e bar ] มีไฟล์ bar หรือไม่? [ "/etc" = $PWD ] /etc เทียบเท่ากับค่าของ $PWD หรือไม่ [ $1 != "secret" ] ค่าของพารามิเตอร์สคริปต์แรกแตกต่างจากสตริงลับหรือไม่? [ 55 -lt $bar ] ค่าจำนวนเต็ม 55 น้อยกว่าค่าของ $bar หรือไม่? [ $foo -ge 1,000 ] ค่าของ $foo มากกว่าหรือเท่ากับค่าจำนวนเต็ม 1,000 หรือไม่? ["เอบีซี"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar ไฟล์ที่สามารถอ่านได้? [ foo -nt bar ] foo ใหม่กว่า bar เหรอ? [ -o nounset ] ตัวเลือก nounset shell เปิดใช้งานอยู่หรือไม่
ตัวดำเนินการตรวจสอบสามารถรวมกับตัวดำเนินการที่เกี่ยวข้องได้ การดำเนินการเชิงตรรกะ"และ" และ "หรือ" paul@RHEL4b:~$ [ 66 -gt 55 -a 66 -lt 500 ] && echo จริง || echo false จริง paul@RHEL4b:~$ [ 66 -gt 55 -a 660 -lt 500 ] && echo true || echo false false paul@RHEL4b:~$ [ 66 -gt 55 -o 660 -lt 500 ] && เสียงสะท้อนจริง || สะท้อนเท็จจริง
กระโดดแบบมีเงื่อนไขถ้าเป็นอย่างอื่น
โครงสร้าง if then else มีวัตถุประสงค์เพื่อเลือกตัวเลือกโค้ด หากเงื่อนไขใดเงื่อนไขหนึ่งเป็นจริง บางโค้ดจะถูกดำเนินการ ไม่เช่นนั้นโค้ดอื่น ๆ บางส่วนจะถูกดำเนินการ ตัวอย่างด้านล่างจะตรวจสอบการมีอยู่ของไฟล์ หลังจากนั้นหากสมมติฐานของการมีอยู่ของไฟล์ได้รับการยืนยัน ข้อความที่เกี่ยวข้องจะปรากฏขึ้น #!/bin/bash ถ้า [ -f isit.txt ] ก็แสดงว่ามีไฟล์ isit.txt อยู่! ไม่พบไฟล์ echo isit.txt! ฟิ
ในกรณีที่เราบันทึก รหัสนี้ในไฟล์ชื่อ "choice" ก็สามารถดำเนินการได้ในลักษณะเดียวกัน ไม่พบไฟล์ $ ./choice isit.txt! $ touch isit.txt $ ./choice มีไฟล์ isit.txt แล้ว! $
กระโดดแบบมีเงื่อนไขถ้าเป็นเอลฟ์
คุณสามารถโพสต์ได้ ผู้ดำเนินการใหม่การกระโดดแบบมีเงื่อนไขหากอยู่ในบล็อกอื่นโดยใช้ตัวดำเนินการ elif ด้านล่างนี้เป็นตัวอย่างง่ายๆ ของรายการดังกล่าว #!/bin/bash count=42 ถ้า [ $count -eq 42 ] ดังนั้น echo "42 เป็นค่าที่ถูกต้อง" elif [ $count -gt 42 ] จากนั้นก้องว่า "มากเกินไป" อย่างอื่นสะท้อนว่า "ไม่เพียงพอ" ฟิ
สำหรับวง
ตัวอย่างด้านล่างแสดงไวยากรณ์ของ for loop แบบคลาสสิกใน bash shell สำหรับฉันใน 1 2 4 สะท้อน $ ฉันทำเสร็จแล้ว
ตัวอย่างของการใช้ for loop รวมกับการเรียกเชลล์แบบอินไลน์ #!/bin/ksh สำหรับตัวนับใน `seq 1 20` ทำเสียงสะท้อนนับจาก 1 ถึง 20 มูลค่าปัจจุบัน $counter sleep 1 เสร็จแล้ว
สคริปต์ที่คล้ายกับที่นำเสนอข้างต้นโดยสิ้นเชิงสามารถสร้างได้โดยไม่ต้องใช้เชลล์คำสั่งแบบฝังโดยใช้การประกาศ bash shell สำหรับช่วงของค่า (จากค่า .. ถึงค่า) #!/bin/bash สำหรับตัวนับใน (1..20) ทำเสียงสะท้อนตั้งแต่ 1 ถึง 20 มูลค่าปัจจุบัน $counter sleep 1 เสร็จแล้ว
for loop นี้ใช้กลไกในการค้นหาไฟล์ตามรูปแบบ (นำไปใช้เป็นส่วนหนึ่งของกลไกการขยายคำสั่ง) หากคำแนะนำข้างต้นถูกโพสต์โดยตรงใน บรรทัดคำสั่งมันก็จะทำงานในลักษณะเดียวกัน kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ สำหรับไฟล์ใน *.ksh ; ทำ cp $file $file.backup ; เสร็จแล้ว kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup
ในขณะที่วนซ้ำ
ด้านล่างนี้เป็นตัวอย่างง่ายๆ ของการใช้ while loop ผม=100; ในขณะที่ [ $i -ge 0 ] ; ทำ echo นับถอยหลังจาก 100 ถึง 0 มูลค่าปัจจุบัน $i; ปล่อยให้ฉัน--; เสร็จแล้ว
การวนซ้ำไม่สิ้นสุดสามารถนำมาใช้ได้โดยใช้การประกาศ while true หรือ while: โดยที่สัญลักษณ์: เทียบเท่ากับการดำเนินการที่ขาดหายไปใน Korn เชลล์และ bash #!/bin/ksh # วนซ้ำไม่สิ้นสุดในขณะที่: ทำ echo สวัสดี sleep 1 เสร็จแล้ว
จนกระทั่งวนซ้ำ
ด้านล่างนี้เป็นตัวอย่างง่ายๆ ของการใช้การวนซ้ำจนกระทั่ง ให้ i=100; จนกระทั่ง [ $i -le 0 ] ; ทำ echo นับถอยหลังจาก 100 ถึง 1 มูลค่าปัจจุบัน $i; ปล่อยให้ฉัน--; เสร็จแล้ว
แบบฝึกหัด: การทดสอบและลูปในสคริปต์
3. พัฒนาสคริปต์ที่จะใช้การวนซ้ำ while เพื่อนับ 3 ถึง 7
4. พัฒนาสคริปต์ที่จะใช้การวนซ้ำจนถึงการนับถอยหลังจาก 8 ถึง 4
5. พัฒนาสคริปต์ที่จะนับไฟล์ที่มีนามสกุล .txt ในไดเร็กทอรีปัจจุบัน
6. ใช้คำสั่ง if ในสคริปต์ที่สร้างขึ้นเพื่อให้ทำงานได้อย่างถูกต้องหากไม่มีไฟล์ที่มีนามสกุล .txt ในไดเร็กทอรีปัจจุบัน
ขั้นตอนที่ถูกต้องในการทำงานภาคปฏิบัติให้เสร็จสิ้น: ตรวจสอบและวนซ้ำในสคริปต์
1. พัฒนาสคริปต์ที่จะใช้ for loop เพื่อนับ 3 ถึง 7
#!/bin/bash for i ใน 3 4 5 6 7 do echo นับจาก 3 ถึง 7 มูลค่าปัจจุบัน $i เสร็จแล้ว
2. พัฒนาสคริปต์ที่จะใช้ for loop เพื่อนับจาก 1 ถึง 17000
bash shell รองรับลูปซึ่งช่วยให้คุณสามารถวนซ้ำลำดับของค่าได้ นั่นคือสิ่งที่มันเป็น โครงสร้างพื้นฐานรอบดังกล่าว:สำหรับคำสั่ง var in list do เสร็จสิ้น
ในการวนซ้ำแต่ละครั้งของลูป ตัวแปร var จะถูกเขียนไปยังค่าถัดไปจาก รายการ. การผ่านครั้งแรกของลูปจะใช้ค่าแรกจากรายการ ในวินาที - วินาทีและอื่น ๆ - จนกระทั่งการวนซ้ำถึงองค์ประกอบสุดท้าย
การวนซ้ำค่าธรรมดา
บางทีตัวอย่างที่ง่ายที่สุดของการ for loop ในสคริปต์ bash คือการวนซ้ำรายการค่าง่าย ๆ :#!/bin/bash สำหรับ var ในวินาทีแรกวินาทีที่สามสี่ห้าทำ echo รายการ $var เสร็จแล้ว
ผลลัพธ์ของสคริปต์นี้แสดงอยู่ด้านล่าง คุณจะเห็นได้อย่างชัดเจนว่าตัวแปร $var มีองค์ประกอบจากรายการตามลำดับ สิ่งนี้จะเกิดขึ้นจนกว่าวงจรจะถึงรอบสุดท้าย
ง่ายสำหรับการวนซ้ำ
โปรดทราบว่าตัวแปร $var จะคงค่าไว้เมื่อออกจากลูป เนื้อหาของตัวแปรสามารถเปลี่ยนแปลงได้ และโดยทั่วไป คุณสามารถทำงานกับตัวแปรดังกล่าวได้เหมือนกับตัวแปรอื่นๆ
การวนซ้ำค่าที่ซับซ้อน
รายการที่ใช้ในการเริ่มต้น for loop ไม่เพียงแต่ประกอบด้วยสตริงธรรมดาที่ประกอบด้วยคำเดียวเท่านั้น แต่ยังรวมถึงวลีทั้งหมดที่มีหลายคำและเครื่องหมายวรรคตอนด้วย ตัวอย่างเช่น อาจมีลักษณะดังนี้:#!/bin/bash สำหรับ var ในอันแรก "อันที่สอง" "อันที่สาม" "ฉันจะทำมัน" ทำเสียงสะท้อน "นี่คือ: $var" เสร็จแล้ว
นี่คือสิ่งที่เกิดขึ้นหลังจากการวนซ้ำนี้ผ่านรายการ อย่างที่คุณเห็นผลลัพธ์ค่อนข้างคาดหวัง
การวนซ้ำค่าที่ซับซ้อน
TNW-CUS-FMP - รหัสโปรโมชั่นส่วนลด 10% สำหรับบริการของเรา เปิดใช้งานได้ภายใน 7 วัน"
การเริ่มต้นการวนซ้ำด้วยรายการที่ได้รับจากผลลัพธ์ของคำสั่ง
อีกวิธีหนึ่งในการเริ่มต้น for loop คือการส่งผ่านรายการ ซึ่งเป็นผลลัพธ์ของคำสั่ง ที่นี่การทดแทนคำสั่งใช้เพื่อดำเนินการและรับผลลัพธ์ของงาน#!/bin/bash file="myfile" สำหรับ var ใน $(cat $file) ทำ echo " $var" เสร็จแล้ว
ตัวอย่างนี้ใช้คำสั่ง cat ซึ่งอ่านเนื้อหาของไฟล์ รายการค่าผลลัพธ์จะถูกส่งผ่านไปยังลูปและแสดงบนหน้าจอ โปรดทราบว่าไฟล์ที่เรากำลังเข้าถึงมีรายการคำที่คั่นด้วยการขึ้นบรรทัดใหม่ ไม่มีการเว้นวรรค
การวนซ้ำที่วนซ้ำเนื้อหาของไฟล์
ที่นี่เราต้องคำนึงว่าแนวทางดังกล่าวหากคาดว่าจะมีการประมวลผลข้อมูลแบบทีละบรรทัดจะไม่ทำงานสำหรับไฟล์ที่มีโครงสร้างที่ซับซ้อนกว่านี้ บรรทัดนั้นอาจมีคำหลายคำคั่นด้วยช่องว่าง การวนซ้ำจะประมวลผลแต่ละคำ ไม่ใช่บรรทัด
จะเกิดอะไรขึ้นถ้านี่ไม่ใช่สิ่งที่คุณต้องการเลย?
เครื่องแยกสนาม
เหตุผลของคุณสมบัติข้างต้นคือความพิเศษ ตัวแปรสภาพแวดล้อมซึ่งเรียกว่า IFS (Internal Field Separator) และอนุญาตให้คุณระบุตัวคั่นฟิลด์ได้ ตามค่าเริ่มต้น bash shell จะถือว่าอักขระต่อไปนี้เป็นตัวคั่นฟิลด์:- ช่องว่าง
- อักขระแท็บ
- อักขระป้อนบรรทัด
เมื่อต้องการแก้ไขปัญหา คุณสามารถเปลี่ยนตัวแปรสภาพแวดล้อม IFS ได้ชั่วคราว ต่อไปนี้เป็นวิธีดำเนินการใน bash script โดยสมมติว่าคุณต้องการเพียงขึ้นบรรทัดใหม่เป็นตัวคั่นฟิลด์:
ไอเอฟเอส=$"\n"
เมื่อคุณเพิ่มคำสั่งนี้ลงในสคริปต์ทุบตีของคุณ มันจะทำงานตามที่คาดไว้ โดยไม่สนใจช่องว่างและแท็บ และถือว่าเฉพาะอักขระขึ้นบรรทัดใหม่เป็นตัวคั่นฟิลด์
#!/bin/bash file="/etc/passwd" IFS=$"\n" สำหรับ var ใน $(cat $file) ทำ echo " $var" เสร็จแล้ว
หากสคริปต์นี้ถูกรัน มันจะส่งออกสิ่งที่ต้องการอย่างแน่นอน โดยให้สิทธิ์ในการเข้าถึงบรรทัดถัดไปที่เขียนลงในไฟล์ในการวนซ้ำแต่ละครั้ง
การข้ามไฟล์ทีละบรรทัดใน for loop
ตัวคั่นสามารถเป็นอักขระอื่นได้ ตัวอย่างเช่น ด้านบนเราได้แสดงเนื้อหาของไฟล์ /etc/passwd ข้อมูลผู้ใช้ในบรรทัดจะถูกคั่นด้วยเครื่องหมายทวิภาค หากคุณต้องการประมวลผลสตริงดังกล่าวในลูป คุณสามารถกำหนดค่า IFS ได้ดังนี้:
การข้ามไฟล์ที่มีอยู่ในไดเร็กทอรี
หนึ่งในการใช้งานที่พบบ่อยที่สุดของ for loops ในสคริปต์ทุบตีคือการสำรวจไฟล์ที่อยู่ในไดเร็กทอรีและประมวลผลไฟล์เหล่านั้นตัวอย่างเช่น ต่อไปนี้เป็นวิธีแสดงรายการไฟล์และโฟลเดอร์:
#!/bin/bash สำหรับไฟล์ใน /home/likegeeks/* do if [ -d "$file" ] จากนั้น echo "$file is a directory" elif [ -f "$file" ] จากนั้น echo "$file is a ไฟล์" เสร็จแล้ว
หากคุณเข้าใจเนื้อหาก่อนหน้านี้ในบทความชุดนี้ คุณควรเข้าใจโครงสร้างของโครงสร้างแบบ if-then รวมถึงวิธีแยกไฟล์ออกจากโฟลเดอร์ หากคุณพบว่าโค้ดข้างต้นเข้าใจได้ยาก โปรดอ่านเนื้อหานี้อีกครั้ง
นี่คือสิ่งที่สคริปต์จะส่งออก
การแสดงเนื้อหาของโฟลเดอร์
ให้ความสนใจกับวิธีที่เราเริ่มต้นการวนซ้ำกล่าวคือ ไวด์การ์ด"*" ที่อยู่ท้ายโฟลเดอร์ สัญลักษณ์นี้สามารถมองได้ว่าเป็นสัญลักษณ์แทน: “ไฟล์ทั้งหมดที่มีชื่อใดก็ได้” ช่วยให้คุณสามารถจัดระเบียบได้ การทดแทนอัตโนมัติชื่อไฟล์ที่ตรงกับรูปแบบ
เมื่อทดสอบเงื่อนไขในคำสั่ง if เราจะใส่ชื่อตัวแปรไว้ในเครื่องหมายคำพูด การดำเนินการนี้เนื่องจากชื่อไฟล์หรือโฟลเดอร์อาจมีช่องว่าง
สไตล์ C สำหรับลูป
หากคุณคุ้นเคยกับภาษาการเขียนโปรแกรม C ไวยากรณ์สำหรับการอธิบาย bash for loops อาจดูแปลกสำหรับคุณ เนื่องจากคุณคุ้นเคยกับการอธิบายลูปในลักษณะนี้อย่างชัดเจน:สำหรับ (i = 0; i< 10; i++)
{
printf("number is %d\n", i);
}
ในสคริปต์ทุบตีคุณสามารถใช้ for loops ได้ คำอธิบายซึ่งดูคล้ายกับลูปสไตล์ C มาก แม้ว่าจะมีความแตกต่างบางประการก็ตาม แผนภาพวงจรด้วยวิธีนี้มีลักษณะดังนี้:
สำหรับ ((ค่าเริ่มต้นของตัวแปร; เงื่อนไขสำหรับการสิ้นสุดลูป; การเปลี่ยนแปลงของตัวแปร))
ใน bash สามารถเขียนได้ดังนี้:
สำหรับ ((a = 1;< 10; a++))
นี่คือตัวอย่างการทำงาน:
#!/bin/bash สำหรับ ((i=1; i<= 10; i++))
do
echo "number is $i"
done
รหัสนี้จะแสดงรายการตัวเลขตั้งแต่ 1 ถึง 10
วนลูปสไตล์ซี
ในขณะที่วนซ้ำ
for build ไม่ใช่วิธีเดียวในการจัดระเบียบลูปในสคริปต์ทุบตี คุณยังสามารถใช้ while ลูปได้ที่นี่ ในลูปดังกล่าว คุณสามารถระบุคำสั่งเพื่อตรวจสอบเงื่อนไขบางอย่างและดำเนินการเนื้อหาของลูปจนกว่าเงื่อนไขที่จะทดสอบจะส่งกลับค่าศูนย์ หรือส่งสัญญาณว่าการดำเนินการบางอย่างเสร็จสมบูรณ์ได้สำเร็จ เมื่อเงื่อนไขลูปส่งคืนค่าที่ไม่ใช่ศูนย์ ซึ่งหมายถึงข้อผิดพลาด การวนซ้ำจะหยุดลงนี่คือไดอะแกรมของการจัดระเบียบของ while loop
ขณะสั่งตรวจสอบสภาพ
ทำ
ทีมอื่นๆ
เสร็จแล้ว
ลองมาดูตัวอย่างสคริปต์ที่มีการวนซ้ำดังนี้:
#!/bin/bash var1=5 ในขณะที่ [ $var1 -gt 0 ] ทำ echo $var1 var1=$[ $var1 - 1 ] เสร็จแล้ว
ที่ทางเข้าสู่ลูป จะมีการตรวจสอบว่าตัวแปร $var1 มากกว่าศูนย์หรือไม่ ถ้าเป็นเช่นนั้น เนื้อความของลูปจะถูกดำเนินการ โดยอันหนึ่งจะถูกลบออกจากค่าของตัวแปร สิ่งนี้จะเกิดขึ้นในการวนซ้ำแต่ละครั้ง และเราจะพิมพ์ค่าของตัวแปรไปยังคอนโซลก่อนที่จะมีการแก้ไข ทันทีที่ $var1 ถึงค่า 0 การวนซ้ำจะหยุดลง
ผลลัพธ์ของการวนซ้ำ while
หากคุณไม่แก้ไขตัวแปร $var1 จะทำให้สคริปต์สิ้นสุดในการวนซ้ำไม่สิ้นสุด
ลูปซ้อนกัน
คุณสามารถใช้คำสั่งใดก็ได้ในส่วนเนื้อหาของลูป รวมถึงการเรียกใช้ลูปอื่นๆ ด้วย โครงสร้างดังกล่าวเรียกว่าลูปแบบซ้อน:#!/bin/bash สำหรับ ((a = 1;<= 3; a++))
do
echo "Start $a:"
for ((b = 1; b <= 3; b++))
do
echo " Inner loop: $b"
done
done
ด้านล่างนี้คือสิ่งที่สคริปต์นี้จะส่งออก อย่างที่คุณเห็น ขั้นแรกให้ทำการวนซ้ำครั้งแรกของวงนอก จากนั้นวนซ้ำสามครั้งในวงใน หลังจากเสร็จสิ้นแล้ว วงนอกจะกลับมาเล่นอีกครั้ง จากนั้นจึงวนซ้ำวงในอีกครั้ง
ลูปซ้อนกัน
กำลังประมวลผลเนื้อหาไฟล์
ส่วนใหญ่มักจะใช้ลูปที่ซ้อนกันเพื่อประมวลผลไฟล์ ดังนั้นลูปด้านนอกกำลังวนซ้ำบรรทัดของไฟล์ และลูปด้านในทำงานกับแต่ละบรรทัดอยู่แล้ว ตัวอย่างเช่น นี่คือลักษณะการประมวลผลไฟล์ /etc/passwd:#!/bin/bash IFS=$"\n" สำหรับการป้อนข้อมูลใน $(cat /etc/passwd) do echo "Values in $entry –" IFS=: สำหรับค่าใน $entry do echo " $value" เสร็จสิ้น เสร็จแล้ว
มีสองลูปในสคริปต์นี้ อันแรกข้ามบรรทัดโดยใช้อักขระขึ้นบรรทัดใหม่เป็นตัวคั่น อันภายในกำลังยุ่งอยู่กับการแยกวิเคราะห์สตริงที่มีฟิลด์คั่นด้วยเครื่องหมายทวิภาค
การประมวลผลข้อมูลไฟล์
วิธีการนี้สามารถนำไปใช้เมื่อประมวลผลไฟล์ CSV หรือไฟล์ที่คล้ายกัน โดยการเขียนอักขระตัวคั่นลงในตัวแปรสภาพแวดล้อม IFS ตามต้องการ
การจัดการวงจร
บางที หลังจากเข้าสู่ลูป คุณจะต้องหยุดเมื่อตัวแปรลูปถึงค่าที่กำหนดซึ่งไม่สอดคล้องกับเงื่อนไขที่ระบุไว้ในตอนแรกสำหรับการสิ้นสุดลูป ในสถานการณ์เช่นนี้ จำเป็นต้องรอให้วงจรเสร็จสิ้นตามปกติหรือไม่? ไม่แน่นอน และในกรณีเช่นนี้ คำสั่งสองคำสั่งต่อไปนี้จะมีประโยชน์:- หยุดพัก
- ดำเนินการต่อ
คำสั่งทำลาย
คำสั่งนี้ช่วยให้คุณสามารถขัดจังหวะการทำงานของลูปได้ สามารถใช้ได้ทั้ง for และ while loops:#!/bin/bash สำหรับ var1 ใน 1 2 3 4 5 6 7 8 9 10 ทำ if [ $var1 -eq 5 ] แล้วทำลาย fi echo "Number: $var1" เสร็จแล้ว
การวนซ้ำดังกล่าวภายใต้สภาวะปกติจะผ่านรายการค่าทั้งหมดจากรายการ อย่างไรก็ตาม ในกรณีของเรา การดำเนินการจะถูกขัดจังหวะเมื่อตัวแปร $var1 เท่ากับ 5
ออกจาก for loop ก่อนกำหนด
นี่คือสิ่งเดียวกัน แต่สำหรับ while loop:
#!/bin/bash var1=1 ในขณะที่ [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] แล้วทำลาย fi echo "Iteration: $var1" var1=$(($var1 + 1)) เสร็จแล้ว
คำสั่ง break ซึ่งดำเนินการเมื่อ $var1 ถึง 5 จะเป็นการหยุดลูป คอนโซลจะแสดงสิ่งเดียวกับในตัวอย่างก่อนหน้า
ดำเนินการคำสั่งต่อไป
เมื่อพบคำสั่งนี้ในเนื้อความของลูป การวนซ้ำปัจจุบันจะสิ้นสุดก่อนกำหนดและการดำเนินการถัดไปจะเริ่มต้นโดยไม่ต้องออกจากลูป ลองดูคำสั่ง Continue ใน For Loop:#!/bin/bash สำหรับ ((var1 = 1; var1< 15; var1++))
do
if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
then
continue
fi
echo "Iteration number: $var1"
done
เมื่อเงื่อนไขภายในลูปเป็นไปตามนั้น นั่นคือเมื่อ $var1 มากกว่า 5 และน้อยกว่า 10 เชลล์จะดำเนินการคำสั่ง Continue ซึ่งส่งผลให้ข้ามคำสั่งที่เหลือในเนื้อความของลูปและไปยังการวนซ้ำครั้งถัดไป
คำสั่ง Continue ใน For Loop
การประมวลผลเอาต์พุตที่ทำงานเป็นวง
เอาต์พุตข้อมูลจากลูปสามารถประมวลผลได้โดยการเปลี่ยนเส้นทางเอาต์พุตหรือส่งผ่านไปยังไปป์ไลน์ ซึ่งทำได้โดยการเพิ่มคำสั่งการประมวลผลเอาต์พุตหลังคำสั่งที่เสร็จสิ้นตัวอย่างเช่น แทนที่จะแสดงบนหน้าจอว่ามีอะไรเอาต์พุตเป็นลูป คุณสามารถเขียนทั้งหมดลงในไฟล์หรือส่งต่อไปที่อื่นได้:
#!/bin/bash สำหรับ ((a = 1;< 10; a++))
do
echo "Number is $a"
done >myfile.txt echo "เสร็จสิ้น"
เชลล์จะสร้างไฟล์ myfile.txt และเปลี่ยนเส้นทางเอาต์พุตของคำสั่ง for ไปยังไฟล์นั้น มาเปิดไฟล์และตรวจสอบให้แน่ใจว่าไฟล์นั้นมีสิ่งที่เราคาดหวัง
เปลี่ยนเส้นทางเอาต์พุตลูปไปยังไฟล์
ตัวอย่าง: ค้นหาไฟล์ปฏิบัติการ
ลองใช้สิ่งที่เราได้กล่าวถึงไปแล้วและเขียนสิ่งที่มีประโยชน์กันดีกว่า ตัวอย่างเช่น หากคุณต้องการค้นหาไฟล์ปฏิบัติการที่มีอยู่ในระบบ คุณสามารถสแกนโฟลเดอร์ทั้งหมดที่บันทึกไว้ในตัวแปรสภาพแวดล้อม PATH เรามีเครื่องมือทั้งหมดที่จำเป็นสำหรับสิ่งนี้อยู่แล้ว เราแค่ต้องรวบรวมมันเข้าด้วยกัน:#!/bin/bash IFS=: สำหรับโฟลเดอร์ใน $PATH ทำ echo "$folder:" สำหรับไฟล์ใน $folder/* ทำถ้า [ -x $file ] แล้ว echo " $file" fi เสร็จแล้ว
สคริปต์นี้มีขนาดเล็กและเรียบง่าย ช่วยให้เราสามารถรับรายการไฟล์ปฏิบัติการที่จัดเก็บไว้ในโฟลเดอร์จาก PATH
ค้นหาไฟล์ปฏิบัติการในโฟลเดอร์จากตัวแปร PATH
ผลลัพธ์
วันนี้เราได้พูดถึง for และ while loops ใน bash scripts วิธีรัน และวิธีจัดการ ตอนนี้คุณรู้วิธีการประมวลผลสตริงที่มีตัวคั่นต่างกันในลูป คุณรู้วิธีเปลี่ยนเส้นทางข้อมูลเอาต์พุตเป็นลูปไปยังไฟล์ วิธีดูและวิเคราะห์เนื้อหาของไดเร็กทอรีหากเราถือว่าคุณเป็นผู้พัฒนาสคริปต์ทุบตีที่รู้เฉพาะสิ่งที่ระบุไว้ในส่วนแรกของบทความชุดนี้และในวินาทีนี้คุณก็สามารถเขียนสิ่งที่มีประโยชน์ได้แล้ว ข้างหน้าคือส่วนที่สาม หลังจากทำความเข้าใจแล้วว่าคุณจะได้เรียนรู้วิธีส่งพารามิเตอร์และสลับบรรทัดคำสั่งไปเป็นสคริปต์ทุบตี และจะทำอย่างไรกับมันทั้งหมด
คำอธิบายสั้น ๆ เกี่ยวกับความแตกต่างในประเภทลูป:
สำหรับ - จะดำเนินการตราบเท่าที่มีวัตถุที่จะดำเนินการ (เช่นการอ่านสตรีมจาก stdin ไฟล์หรือฟังก์ชัน)
ในขณะที่ - ดำเนินการจนกระทั่ง เงื่อนไขเป็นความจริง;
จนกระทั่ง - จะถูกดำเนินการตราบเท่าที่ เงื่อนไขจะไม่เป็นจริงเช่น สำหรับตอนนี้มันเป็นเท็จ
สำหรับห่วง
ลองพิจารณาสคริปต์เวอร์ชันนี้แบบวนซ้ำ:
$ cat loop.sh #!/bin/bash สำหรับตัวแปรใน `ls -1` ทำ echo "$variable" เสร็จแล้ว
ไวยากรณ์นั้นง่ายมากและแสดงให้เห็นอย่างชัดเจนในตัวอย่าง:
สำหรับ (เริ่มลูป) ตัวแปร (ประกาศตัวแปรที่เราจะดำเนินการ) ใน (ส่งโฟลว์ไปยังลูป) `ls -1` (คำสั่งที่จะดำเนินการและส่งผ่านไปยังตัวแปร $variable) สิ่งที่ทำและทำเสร็จแล้วคือ "เนื้อหา" ของลูป ซึ่งภายในการดำเนินการหลักจะดำเนินการกับข้อมูลที่ได้รับ และเสียงสะท้อน "$variable" คือการกระทำจริงที่ดำเนินการโดยลูป
ตอนนี้เรามาเปลี่ยนตัวอย่างกันสักหน่อย และแทนที่จะระบุคำสั่งอย่างชัดเจน เราจะใช้ตัวแปรตัวที่สอง:
$ cat loop.sh #!/bin/bash ls=`ls -1` สำหรับตัวแปรใน $ls ทำ echo "$variable" เสร็จแล้ว
ตอนนี้คำสั่ง ls -1 ถูกส่งผ่านในตัวแปรแยกต่างหาก ซึ่งช่วยให้คุณทำงานกับลูปได้อย่างยืดหยุ่นมากขึ้น แทนที่จะใช้ตัวแปรในลูป คุณยังสามารถใช้ฟังก์ชันได้:
$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) สำหรับตัวแปรใน `lsl` ทำ echo "$variable" เสร็จแล้ว
เงื่อนไขหลักของ for loop คือมันจะถูกดำเนินการตราบใดที่คำสั่งที่ส่งไปนั้นมีออบเจ็กต์สำหรับการดำเนินการ ตามตัวอย่างด้านบน - ตราบใดที่ ls -1 มีไฟล์ที่จะแสดง - ลูปจะส่งผ่านไฟล์เหล่านั้นไปยังตัวแปรและดำเนินการ "loop body" ทันทีที่รายการไฟล์ในไดเร็กทอรีสิ้นสุดลง ลูปจะดำเนินการให้เสร็จสิ้น
มาทำให้ตัวอย่างซับซ้อนขึ้นอีกหน่อย
ไดเรกทอรีประกอบด้วยรายการไฟล์:
$ ls -1 file1 file2 file3 file4 file5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5
เราต้องเลือกจากพวกเขาเฉพาะที่ไม่มีคำว่า " เลขที่«:
$ cat loop.sh #!/bin/bash lsl=`ls -1` สำหรับตัวแปรใน $lsl do echo "$variable" | grep -v "ไม่" เสร็จแล้ว $ ./loop.sh file1 file2 file3 file4 file5 loop.sh
คุณยังสามารถใช้นิพจน์แบบมีเงื่อนไขในลูป ( การแสดงออกตามเงื่อนไข) […] เพื่อตรวจสอบเงื่อนไขและคำสั่งแบ่งเพื่อขัดจังหวะลูปหากเงื่อนไขถูกทริกเกอร์
ลองพิจารณาตัวอย่างนี้:
$ cat loop.sh #!/bin/bash lsl=`ls -1` สำหรับตัวแปรใน $lsl do if [ $variable != "loop.sh" ] จากนั้น echo "$variable" | grep -v "no" อย่างอื่นพังเสร็จเรียบร้อย
การวนซ้ำจะดำเนินต่อไปจนกว่าจะพบไฟล์ loop.sh ทันทีที่การดำเนินการของลูปมาถึงไฟล์นี้ ลูปจะถูกขัดจังหวะด้วยคำสั่ง break:
$ ./loop.sh ไฟล์1 ไฟล์2 ไฟล์3 ไฟล์4 ไฟล์5
อีกตัวอย่างหนึ่งคือการใช้การดำเนินการทางคณิตศาสตร์ทันทีก่อนดำเนินการเนื้อความของลูป:
$ cat loop.sh #!/bin/bash สำหรับ ((count=1; count<11; count++)) do echo "$count" done
ที่นี่เราตั้งค่าคำสั่งควบคุมสามคำสั่ง - count=1, เงื่อนไขการควบคุม - ในขณะที่จำนวนน้อยกว่า 11 และคำสั่งให้ดำเนินการ - count +1:
WHILE และ UNTIL วนซ้ำ
ตัวอย่างง่ายๆ ที่แสดงให้เห็นอย่างชัดเจนว่า while loop ทำงานอย่างไร:
$ cat loop.sh #!/bin/bash count=0 ในขณะที่ [ $count -lt 10 ] do ((count++)) echo $count เสร็จแล้ว
เราตั้งค่าตัวแปร $count ให้เป็นศูนย์ จากนั้นรันคำสั่ง whi le โดยมีเงื่อนไข “ในขณะที่ $count น้อยกว่าสิบ ให้ดำเนินการลูป” ในเนื้อความของลูปที่เราดำเนินการ การเพิ่มขึ้นภายหลัง+1 ให้กับตัวแปร $count และผลลัพธ์จะถูกพิมพ์ไปที่ stdout
ผลการดำเนินการ:
$ ./loop.sh 1 2 3 4 5 6 7 8 9 10
ทันทีที่ค่าของตัวแปร $count กลายเป็น 10 การวนซ้ำก็หยุดลง
ตัวอย่างที่ดีของการวนซ้ำแบบ "ไม่มีที่สิ้นสุด" ที่สาธิตวิธีการทำงานของ while:
$ cat loop.sh #!/bin/bash count=10 ในขณะที่ [ 1 = 1 ] ทำ ((นับ++)) echo $count เสร็จแล้ว $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C
การวนซ้ำจนกระทั่งทำงานในลักษณะเดียวกัน แต่ไปในทิศทางตรงกันข้าม:
$ cat loop.sh #!/bin/bash count=0 จนถึง [ $count -gt 10 ] do ((count++)) echo $count เสร็จสิ้น
ที่นี่เราตั้งค่าเงื่อนไขที่คล้ายกัน แต่แทนที่จะระบุ "ในขณะที่ตัวแปรน้อยกว่า 10" เราระบุ "จนกว่าตัวแปรจะมีค่ามากกว่า 10" ผลการดำเนินการ:
$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11
หากตัวอย่างข้างต้นของ “endless loop” ถูกดำเนินการโดยใช้ until มันจะไม่ส่งออกสิ่งใด ซึ่งแตกต่างจาก while:
$ cat loop.sh #!/bin/bash count=10 จนถึง [ 1 = 1 ] do ((count++)) echo $count เสร็จแล้ว $ ./loop.sh $
เพราะ " เงื่อนไข"เดิมที" จริง"—เนื้อความของลูปจะไม่ถูกดำเนินการ
เช่นเดียวกับใน for loop คุณสามารถใช้ฟังก์ชันใน while และ until ได้ ตัวอย่างเช่น การวนซ้ำจากสคริปต์ในชีวิตจริงที่ตรวจสอบสถานะของเซิร์ฟเวอร์ แมวตัวผู้(PID ถูกนำมาจากระบบ สลสอาจแตกต่างกันในระบบอื่น) เวอร์ชันที่เรียบง่ายเล็กน้อย:
$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(พิมพ์ $2)"` ) ในขณะที่ check_tomcat_status ทำถ้า [ -n "$ RUN" ] จากนั้น printf "คำเตือน: Tomcat ยังคงทำงานโดยมี PID $RUN" อย่างอื่น printf "Tomcat หยุด ดำเนินการต่อ...nn" พังเสร็จเรียบร้อย
ผลการดำเนินการ:
$ ./loop.sh คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคง ทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435 26548 คำเตือน: Tomcat ยังคงทำงานด้วย PID 14435
เวอร์ชันเต็ม:
Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(พิมพ์ $2)"` ) ในขณะที่ check_tomcat_status; จะทำอย่างไรถ้า [ -n "$RUN" ] จากนั้น printf "คำเตือน: Tomcat ยังคงทำงานด้วย PID $RUN หยุดไหม " ตอบ "หยุด Tomcat..." "กำลังดำเนินการติดตั้ง..." && $CATALINA_HOME/bin/shutdown . sh 2&>1 /dev/null || พัก sleep 2 ถ้า [ -n "$RUN" ] แล้ว printf "Tomcat ยังคงทำงานอยู่ ฆ่ามันเหรอ" ตอบ "กำลังฆ่า Tomcat..." "กำลังดำเนินการติดตั้ง...n" && kill $RUN || พักนอน 2 อย่างอื่น printf "Tomcat หยุดแล้วดำเนินการต่อ ... nn" พักเสร็จเรียบร้อยแล้ว
ฟังก์ชันคำตอบได้อธิบายไว้ในบทความ แต่มีการใช้เวอร์ชันที่ได้รับการปรับปรุงเล็กน้อย:
คำตอบ () ( ขณะที่อ่านคำตอบ ทำ echo case $response ใน |) printf "$1n" return 0 break ;; |) printf "$2n" คืน 1 ตัวแบ่ง ;; *) printf "กรุณากรอก Y(ใช่) หรือ N(no)! " esac เสร็จสิ้น )
ที่นี่คุณสามารถใช้ทั้ง while และ until - แต่ไม่ใช่ for loop เนื่องจาก for ใช้งานได้ครั้งเดียว (รับ PID และสิ้นสุด)
การวนซ้ำเป็นสิ่งที่สะดวกอย่างยิ่งเมื่อเขียนโปรแกรมหรือสคริปต์ใดๆ แม้จะจำเป็นก็ตาม พวกมันอนุญาตให้เรารันโค้ดบางส่วนตามจำนวนครั้งที่ระบุ โดยธรรมชาติแล้ว bash มีลูปหลายประเภท เราจะอธิบายวงจร สำหรับใน, สำหรับ, ในขณะที่, จนกระทั่ง. แม้ว่า for in และ for จะถือเป็นไวยากรณ์ที่แตกต่างกันของข้อความเดียวกัน แต่ในความคิดของฉัน มันแตกต่างกันมากกว่า while from until
ห่วงพร้อมตัวนับสำหรับเข้า:
วงจร สำหรับในนี่คือการวนซ้ำพร้อมตัวนับ บล็อกของโค้ดที่อยู่ในเนื้อหาของลูปจะถูกทำซ้ำหลาย ๆ ครั้งตามที่มีค่าที่มีอยู่ในรายการของ for in โอเปอเรเตอร์ และในการทำซ้ำแต่ละครั้งตัวแปรตัวนับ (ในที่นี้เรียกว่า var แต่แน่นอน คุณสามารถเรียกมันว่าอะไรก็ได้ที่คุณต้องการ) มีค่าขององค์ประกอบถัดไปของรายการ
หากคีย์เวิร์ด do อยู่ในบรรทัดเดียวกับคำว่า for คุณจะต้องใส่เครื่องหมายอัฒภาคหลังรายการอาร์กิวเมนต์ (ก่อนทำ)
แต่ละองค์ประกอบ<список>อาจมีหลายข้อโต้แย้ง สิ่งนี้มีประโยชน์เมื่อประมวลผลกลุ่มของพารามิเตอร์ ในกรณีนี้ เพื่อบังคับให้แยกวิเคราะห์ข้อโต้แย้งแต่ละรายการ<списке>คุณต้องใช้คำสั่งชุด
คุณสามารถใช้ตัวแปรเป็นรายการใน for loop ได้
ใน<списке>for loop สามารถใช้ชื่อไฟล์ ซึ่งในทางกลับกันสามารถมีอักขระไวด์การ์ดได้ สิ่งนี้มีประโยชน์มากเมื่อทำงานกับไฟล์จำนวนมาก
ถ้า<список>ไม่ได้ระบุใน for loop จากนั้นจึงใช้ตัวแปร $@ เป็นรายการอาร์กิวเมนต์บรรทัดคำสั่ง
เมื่อสร้างรายการอาร์กิวเมนต์ คุณสามารถใช้การทดแทนคำสั่งใน for loop ได้
เอาต์พุตของการวนซ้ำสามารถเปลี่ยนเส้นทางจาก stdout ไปยังไฟล์หรือที่อื่นได้ (คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับสิ่งนี้ได้โดยดูที่การเปลี่ยนเส้นทาง I/O)
ไวยากรณ์:
สำหรับ var in<список>
ทำ
<выполняемые команды>
เสร็จแล้ว
ตัวอย่าง:
สำหรับชื่อในชื่อ1 ชื่อ2 ชื่อ3 ชื่อ4
ทำ
สะท้อนชื่อ $
เสร็จแล้ว
ตัวดำเนินการวนซ้ำ สำหรับมีวิธีการเขียนอีกวิธีหนึ่ง - คล้ายกับไวยากรณ์ของตัวดำเนินการ for ในภาษา C มาก ในกรณีนี้เมื่อเริ่มต้นตัวนับจะมีการตั้งค่าค่าเริ่มต้นของตัวแปรหรือตัวแปรหนึ่งตัวและหลังจากผ่านลูปแต่ละครั้งจะมีเงื่อนไข ถูกเลือก หากเช็คคืนค่าเป็นจริง การวนรอบครั้งถัดไปจะเริ่มต้นขึ้น ในบล็อก<приращение счётчиков>ค่าของตัวนับตัวแปรของเราต้องเปลี่ยนแปลง (ไม่จำเป็นต้องสูงขึ้น) เพื่อว่าเมื่อตรวจสอบเงื่อนไข ไม่ช้าก็เร็วเราจะได้ค่าเท็จ ไม่เช่นนั้นการวนซ้ำจะไม่มีวันสิ้นสุด ตัวเลือกที่สะดวกและคุ้นเคยที่สำคัญที่สุดหากจำเป็นต้องทำซ้ำตามจำนวนที่ระบุ
ด้วยไวยากรณ์ที่คล้ายกัน:
สำหรับ ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
ทำ
<выполняемые команды>
เสร็จแล้ว
ตัวอย่าง:
สำหรับ ((var=1; var<= LIMIT ; var++))
ทำ
เสียงสะท้อน $var
เสร็จแล้ว
ในขณะที่วนซ้ำ:
นี่เป็นโครงสร้างที่ค่อนข้างง่ายที่จะตรวจสอบสภาพเบื้องหลังของผู้ปฏิบัติงาน ในขณะที่และหากเงื่อนไขนี้เป็นจริง มันจะดำเนินการบล็อกของคำสั่งที่อยู่ระหว่างคำว่า do และ Done จากนั้นจึงดำเนินการตรวจสอบเงื่อนไขอีกครั้ง หากการตรวจสอบส่งคืนเท็จ รอบจะสิ้นสุดและคำสั่งต่อไปนี้จะเริ่มดำเนินการ: เสร็จแล้ว. จำเป็นอย่างยิ่งที่จะต้องแน่ใจว่า<проверка условия>ขึ้นอยู่กับโค้ดที่ทำงานอยู่ในลูป มิฉะนั้น หากผลลัพธ์ของการตรวจสอบไม่เปลี่ยนแปลง คุณจะเกิดการวนซ้ำไม่สิ้นสุด
อุปกรณ์อินพุตมาตรฐานสำหรับลูป while สามารถเปลี่ยนเส้นทางไปยังไฟล์ได้โดยใช้คำสั่งการเปลี่ยนเส้นทาง< в конце цикла.
ไวยากรณ์:
ในขณะที่<Проверка условия>
ทำ
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
เสร็จแล้ว
ตัวอย่าง:
ในขณะที่ [ $var0 -eq 100 ]
ทำ
เสียงสะท้อน $var
วาร์++
เสร็จแล้ว
ผู้ดำเนินการ ในขณะที่อาจมีเงื่อนไขหลายประการ แต่มีเพียงคนสุดท้ายเท่านั้นที่จะกำหนดความเป็นไปได้ในการดำเนินวงจรต่อไป ในกรณีนี้ ไวยากรณ์ของตัวดำเนินการลูปจะแตกต่างจากรูปแบบปกติ
ไวยากรณ์(ฉันขอย้ำอีกครั้งว่าเฉพาะเงื่อนไขสุดท้ายเท่านั้นที่ส่งผลต่อการดำเนินการของลูป) :
ในขณะที่
<условие1>
<условие2>
<условиеN>
ทำ
<выполняемые команды - тело цикла>
เสร็จแล้ว
จนกระทั่งวนซ้ำ:
ผู้ดำเนินการ จนกระทั่งคล้ายกับ while มาก นอกจากนี้ยังประเมินเงื่อนไขด้วย แต่จะประมวลผลเนื้อความของลูปหากผลลัพธ์ของการคำนวณเป็นเท็จ อาจดูผิดปกติ แต่จนกระทั่งประเมินเงื่อนไขก่อนที่จะผ่านครั้งแรกของลูป เช่น ในขณะที่ ไม่ใช่หลังจากนั้น เช่นเดียวกับ for/in loops เมื่อวางคีย์เวิร์ด do ในบรรทัดเดียวกับการประกาศ loop คุณต้องแทรกอักขระ ";" ก่อนทำ
เช่นเดียวกับในกรณีก่อนหน้านี้ สิ่งสำคัญคือต้องจำไว้ว่าเงื่อนไขต้องขึ้นอยู่กับการดำเนินการในเนื้อหาของลูป ไม่เช่นนั้นสคริปต์ของเราจะไม่มีวันเสร็จสมบูรณ์
ไวยากรณ์:
จนกระทั่ง<Проверка условия>
ทำ
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
เสร็จแล้ว
ตัวอย่าง:
จนถึง [ $var0 -gt 100] # มีการตรวจสอบเงื่อนไขเมื่อเริ่มต้นการวนซ้ำ
ทำ
เสียงสะท้อน $var
วาร์--
เสร็จแล้ว
ก็น่าจะเพียงพอแล้วสำหรับตอนนี้ :)
- กลับ
- ซึ่งไปข้างหน้า
บทความใหม่:
- การค้นพบเครือข่ายไม่เปิดขึ้นใน Windows 7/8/2008/2012
- ข้อผิดพลาด: แอปพลิเคชันนี้ไม่สามารถเริ่มทำงานได้เนื่องจากไม่พบหรือโหลดปลั๊กอินแพลตฟอร์ม Qt "windows"
- การกำหนดค่าการรีสตาร์ทอัตโนมัติของกระบวนการของผู้ปฏิบัติงาน rphost.exe บนเซิร์ฟเวอร์ 1C 8.3
-
วิธีการลดขนาดของบันทึกธุรกรรม (.ldf) ใน MS SQL 2008/20012
MS SQL เช่นเดียวกับ DBMS อุตสาหกรรมที่ดีอื่นๆ พร้อมด้วยฐานข้อมูล จะเก็บบันทึกธุรกรรมที่ช่วยให้คุณสามารถย้อนกลับสถานะ...
0 มีรัน บาลา-กุมารัน
ฉันกำลังพยายามเข้าใจจริงๆ ว่าทำไมการวนซ้ำ while จึงไม่สิ้นสุด เมื่อการวนซ้ำเริ่มต้น ตัวแปร LOC ของฉันถูกตั้งค่าเป็น Testing/ ซึ่งเป็นไดเร็กทอรีที่ฉันสร้างขึ้นเพื่อทดสอบโปรแกรมนี้มีเลย์เอาต์ดังต่อไปนี้:
ฉันต้องการให้การวนซ้ำสิ้นสุดเมื่อไดเร็กทอรีทั้งหมดใช้ฟังก์ชัน "นับ" แล้ว
นี่คือสิ่งที่ฉันลอง
ฉันตรวจสอบฟังก์ชันการนับแล้ว แต่มันไม่สร้างการวนซ้ำไม่สิ้นสุด
ฉันพยายามเรียกใช้อัลกอริทึมด้วยตนเอง
PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") ในขณะที่ [ $PARSE = "1" ] do if [[ $(AVAILABLEDIR[@]) == "" ]]; จากนั้น PARSE=0 fi DIRBASE=$LOC สำหรับ a ใน $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" นับเสร็จแล้วสำหรับ a ใน $(LOCLIST[@]); ทำ TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( พิมพ์ $9 )") PREPEND=$a ถ้า [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; จากนั้นดำเนินการต่อ fi สำหรับ a in $(TMPAVAILABLEDIR[@]); ทำ TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" เสร็จสิ้น NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" เสร็จสิ้น AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" เสร็จสิ้น
ฉันกำลังดิ้นรนจริงๆ และข้อเสนอแนะใดๆ จะได้รับการชื่นชมอย่างมาก ฉันพยายามคิดหาคำตอบนี้ในช่วงสองชั่วโมงที่ผ่านมา
ทุบตีวงอนันต์
4 คำตอบ
คุณควรลองรันสคริปต์ด้วยอาร์กิวเมนต์ -x หรือเขียนไว้ในบรรทัดแรก:
#!/bin/bash -x
จากนั้นเขาจะบอกคุณทุกอย่างที่เขาทำ
ในกรณีนี้ คุณอาจสังเกตเห็นข้อผิดพลาดสองประการ:
คุณไม่เคยโหลด TMPAVAILABLEDIR2 ใหม่
คุณยังทำ ls กับไฟล์ปกติด้วย
หากคุณต้องหลีกเลี่ยงการเรียกซ้ำจริงๆ ให้ลองทำสิ่งนี้โดยสมบูรณ์โดยไม่ต้องเรียกซ้ำ:
#!/bin/bash count() ( echo counting "$1" ) todo=(Testing) while test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () สำหรับ dir ใน "$(doit[@])" do สำหรับรายการใน "$dir"/* # ถ้า dir ว่างเปล่า นี่จะแสดงรายการชื่อ "*" do test -e "$entry" || ดำเนินการต่อ # ข้ามรายการ "*" ของจำนวน dir ที่ว่างเปล่า "$entry" test -d "$entry" || Continue todo+=("$entry") เสร็จแล้ว เสร็จแล้ว
อย่างไรก็ตาม โปรดบอกฉันว่าทำไมคุณไม่สามารถใช้การเรียกซ้ำได้ อาการแบบนี้เป็นภูมิแพ้หรือเปล่า? คำสาบาน? มีกฎหมายท้องถิ่นเกี่ยวกับซอฟต์แวร์แบบเรียกซ้ำในที่ที่คุณอาศัยอยู่หรือไม่?
คุณเขียนว่าคุณต้องการ "นับ" ในการตัดทั้งหมด ตรวจสอบตัวเลือกการค้นหา:
ค้นหา $LOC -พิมพ์ d | ในขณะที่อ่าน dir; ทำ cd $LOC cd $(dir) นับเสร็จแล้ว
หรือสั้นกว่า (เมื่อตัวนับฟังก์ชันของคุณรับไดเร็กทอรีเป็นพารามิเตอร์ 1)
ค้นหา $LOC -พิมพ์ d | xargs นับ
ตอนนี้ฉันเห็นว่าคุณไม่ต้องการใช้ find หรือ ls -R (ฟังก์ชันเรียกซ้ำ) จากนั้นคุณควรสร้างฟังก์ชันแบบเรียกซ้ำของคุณเองเช่น
ฟังก์ชั่น parseDir ( ls -d */ $1 | ในขณะที่อ่าน dir; ให้นับ parseDir $1/$dir เสร็จสิ้น)
ฉันไม่รู้ว่าสิ่งนี้จะได้ผลหรือไม่ แต่เป็นคำถามที่น่าสนใจที่ฉันหยุดคิดไม่ได้เลย ขอให้โชคดี
ในขณะที่จริง; ทำเพื่อคำใน "$(echo *)" ; ทำ if [[ -d "$word" ]] ; จากนั้น d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ; จากนั้น f[$((j++))]="$PWD"/"$ word" fi เสร็จแล้ว [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || พังเสร็จแล้ว