สตรีม ช่องรายการ และการเปลี่ยนเส้นทาง สคริปต์สำรองข้อมูลอย่างง่าย

วันนี้เราจะเริ่มดูความสามารถของ bash เนื่องจากคำถามนี้ค่อนข้างกว้าง จึงต้องแบ่งออกเป็นหลายส่วน เริ่มจากง่ายไปซับซ้อนกันดีกว่า อย่างไรก็ตาม มีความเป็นไปได้สูงมากที่ข้อมูลที่ได้รับในระหว่างนั้น การเรียนรู้ทุบตีจะมีประโยชน์เมื่อทำงานกับล่ามคำสั่งอื่น
สตรีมอินพุตและเอาท์พุตมาตรฐาน
แนวคิดที่ค่อนข้างสำคัญเหล่านี้หมายถึงตำแหน่งที่โปรแกรมอ่านข้อมูลตามค่าเริ่มต้น (stdin) และตำแหน่งที่เอาต์พุตผลลัพธ์ของงาน (stdout) นอกจากนี้ยังมีสตรีมเอาต์พุตข้อผิดพลาดมาตรฐาน (stderr) โดยปกติแล้วนี่คือหน้าจอ (เทอร์มินัลผู้ใช้) + แป้นพิมพ์ ทำไมคุณต้องรู้เรื่องนี้? แต่ความจริงก็คือว่าโฟลว์ทั้งหมดนี้สามารถเปลี่ยนเส้นทางได้ ส่วนใหญ่แล้วไฟล์จะถูกใช้สำหรับ I/O
ตัวอย่างเช่น วิธีนี้คุณสามารถสร้างไฟล์ที่มีรายการไฟล์ในไดเร็กทอรีที่ระบุได้
$ ls -l > ~/file_with_files
อย่างไรก็ตาม ควรจำไว้ว่าครั้งต่อไปที่คุณเรียกใช้งาน ไฟล์จะถูกเขียนใหม่ทั้งหมด และทุกสิ่งที่อยู่ตรงนั้นจะหายไป หากคุณต้องการต่อท้ายไฟล์ คุณต้องใช้ ">>" แทน ">"
$ ls -l >> ~/file_with_files
นอกจากนี้ เมื่อดำเนินการคำสั่ง คุณสามารถแยกเธรดได้
stdin คือหมายเลข 0
stdout คือหมายเลข 1
stderr คือหมายเลข 2
นั่นคือคุณสามารถส่งออกข้อผิดพลาดไปยังไฟล์แยกต่างหากและ ข้อความปกติจะแสดงตามปกติ ในการดำเนินการนี้ คุณต้องใส่หมายเลข 2 ไว้หน้า ">" (หมายเลขเธรด เช่นเดียวกับ stdin, stdout) เช่นแบบนี้
$ ค้นหา / - ​​ชื่อ .bashrc 2> ~/finderrors.txt
นอกจากนี้ยังมีอุปกรณ์ชื่อ /dev/null ซึ่งคุณสามารถเปลี่ยนเส้นทางเอาต์พุตได้ ในกรณีนี้ จะไม่มีการแสดงสิ่งใดที่ส่งไปที่ไหนเลย
$ ค้นหา / -name asdf 2 > /dev/null
เอาต์พุตยังสามารถส่งไปยังคำสั่งอื่นได้ ตัวอย่างเช่น คำสั่งต่อไปนี้จะพิมพ์จำนวนคำในไฟล์
$ cat ~/finderrors.txt > wc -w
หากคุณต้องการเขียนสคริปต์ที่บางโปรแกรมต้องการอินพุตคุณสามารถส่งเนื้อหาของไฟล์ไปได้
$ สุขา -w< ~/finderrors.txt
บันทึก. ">" โดยไม่ระบุหมายเลขเธรดจะถูกตีความว่าเป็น "1 >" นั่นคือเฉพาะ stdin เท่านั้นที่จะส่งออก
สายพานลำเลียง
แน่นอนคุณได้เห็นทีม ประเภทต่อไปนี้:
$ cat /etc/bash.bashrc | มากกว่า
ผลจากการทำงาน เอาต์พุตจะหยุดชั่วคราวเมื่อเต็มหน้าจอ ดังนั้น "|" และก็มีสายพานลำเลียงแบบนี้ด้วย ในแง่ที่ชาญฉลาด นี่เป็นช่องทางที่กระบวนการหนึ่งสามารถเขียนได้เท่านั้น และอีกกระบวนการหนึ่งสามารถอ่านได้เท่านั้น การสุ่มตัวอย่างและการวางลงในสายพานลำเลียงดังกล่าวเป็นไปตามหลักการ FIFO (เข้าก่อน - ออกก่อน) หลักการนี้เรียกอีกอย่างว่าคิวซึ่งแสดงลักษณะการทำงานของมันอย่างง่ายดายและแม่นยำ ไปป์ไลน์ใช้เพื่อรวมการทำงานของโปรแกรมขนาดเล็กหลายโปรแกรม
มาดูการทำงานของคำสั่งต่อไปกัน
$ แมว myfile | grep Linux | เรา -1
ขั้นแรก cat myfile จะพิมพ์เนื้อหาของไฟล์ myfile จากนั้น grep Linux จะอ่านเอาต์พุตและเลือกเฉพาะบรรทัดที่มีคำว่า Linux จากนั้น wc -l นับจำนวนบรรทัด ผลลัพธ์ที่ได้คือจำนวนบรรทัดที่มีคำว่า Linux
การใช้ยูทิลิตี้ xargs ร่วมกับ “|” สะดวกมาก xargs อ่านองค์ประกอบเอาต์พุต stdin ที่คั่นด้วยช่องว่างและรันโปรแกรมโดยส่งผ่านองค์ประกอบเหล่านั้นหนึ่งครั้งหรือมากกว่านั้น
ตัวอย่างเช่น
$ find /tmp -name core -type f -print | xargs /bin/rm -f
คำสั่งนี้ค้นหาไฟล์ชื่อ core ในไดเร็กทอรี /tmp และลบออก
สัญลักษณ์พิเศษ
ไม่เหมือนกับ Windows ชื่อไฟล์ใน Linux สามารถมีอักขระได้เกือบทุกชนิด (เช่น ชื่อไฟล์ example*of:file ค่อนข้างเป็นไปได้) แต่ bash ใช้อักขระบางตัวเป็นอักขระบริการ และสำหรับ การดำเนินการที่ถูกต้องตัวละครเหล่านี้จำเป็นต้องหลบหนี ซึ่งสามารถทำได้หลายวิธี
คุณสามารถใส่นิพจน์ในเครื่องหมายคำพูดได้ ตัวอย่างเช่น
$ cp "ตัวอย่าง * ของ: ไฟล์" ~
คุณยังสามารถใช้เครื่องหมายคำพูดเดี่ยวได้
$ cp "ตัวอย่าง * ของ: ไฟล์" ~
ข้อแตกต่างคือในเครื่องหมายคำพูดเดี่ยวอักขระพิเศษทั้งหมดจะสูญเสียความหมาย ส่วนเครื่องหมายคำพูดคู่ - ทั้งหมดยกเว้น $ และ \
แต่วิธีที่เป็นสากลที่สุดคือวิธีการยกเลิกอักขระพิเศษแบบ C ในการดำเนินการนี้ เพียงใส่ “\” (โดยไม่ใส่เครื่องหมายคำพูด) หน้าสัญลักษณ์ ตัวอย่างเช่น คำสั่งของเราจะมีลักษณะเช่นนี้
ตัวอย่าง $ cp\*of\:file ~
การดำเนินการคำสั่ง
มีสัญลักษณ์หลายอย่างสำหรับจัดระเบียบการดำเนินการตามคำสั่ง
หากคุณต้องการดำเนินการหลายคำสั่งตามลำดับ ควรแยกคำสั่งเหล่านั้นด้วยสัญลักษณ์ “;” ตัวอย่างเช่น, ลำดับถัดไปจะทำการคอมไพล์ไฟล์ (และการคอมไพล์เป็นกระบวนการที่ยาว ในช่วงนี้คุณสามารถพักเครื่องได้!) จากนั้นจึงปิดคอมพิวเตอร์
$ ทำ ; sudo ปิดเครื่อง -h ตอนนี้
หากจำเป็นต้องรันโปรแกรม พื้นหลัง(นั่นคือคืนการควบคุมให้กับผู้ใช้ทันทีหลังจากเปิดตัวซึ่งจะสะดวกเมื่อเปิดแอปพลิเคชันกราฟิก) จากนั้นคุณต้องใส่สัญลักษณ์ "&" หลังคำสั่ง ตัวอย่างเช่น
$sudo ซินแนปติก &
เป็นผลให้ synaptic เริ่มทำงานและเราสามารถใช้โปรแกรมจำลองเทอร์มินัลปัจจุบันได้โดยไม่ต้องทิ้งมันไว้
แต่จะเกิดอะไรขึ้นถ้าเราจำเป็นต้องดำเนินการคำสั่งเฉพาะในกรณีที่การดำเนินการเสร็จสมบูรณ์ ตัวอย่างเช่น มีงานต่อไปนี้:
คุณต้องคอมไพล์ไฟล์. ในการดำเนินการนี้ คุณจะต้องเรียกใช้ configuration, make, sudo make install ยิ่งไปกว่านั้น จะต้องดำเนินการเฉพาะเมื่อคำสั่งก่อนหน้าสิ้นสุดลงสำเร็จเท่านั้น
ในกรณีเช่นนี้ จะใช้ลำดับ "&&" ตัวดำเนินการหลัง "&&" จะถูกดำเนินการเฉพาะเมื่อตัวดำเนินการก่อนหน้านี้เสร็จสมบูรณ์แล้วเท่านั้น นั่นคือสำหรับเรามันจะเป็นดังนี้:
$ ./configure && make && sudo ทำการติดตั้ง
หากคุณต้องการดำเนินการเฉพาะเมื่อโปรแกรมลงท้ายด้วยข้อผิดพลาด คุณต้องใช้ "||" ตัวอย่างเช่น ลองทำให้ปัญหาซับซ้อนขึ้น หากมีข้อผิดพลาดคุณจะต้องเขียนลงในไฟล์จากนั้นปิดคอมพิวเตอร์ไม่ว่าท้ายที่สุดจะเป็นอย่างไร
$ ./configure && ทำ && ทำการติดตั้ง || เสียงสะท้อนล้มเหลว > ~/errorfile ; sudo ปิดเครื่อง -h ตอนนี้
รูปแบบชื่อไฟล์
วิธีที่ง่ายที่สุดคือการจดรายการไว้บนจาน โปรดจำไว้ว่าเทมเพลตสามารถรวมไว้ในคำสั่งเดียวได้
ความหมายของรูปแบบ
* ลำดับของอักขระใดๆ รวมถึงอักขระว่างด้วย
- อักขระตัวใดตัวหนึ่ง
(a,b,c,d) อักขระใดๆ ที่อยู่ในวงเล็บ
อักขระใดๆ จากช่วงเวลาที่ระบุ
[^0-6] อักขระใดๆ ที่ไม่รวมอยู่ในช่วงเวลาที่ระบุ
วิธีที่ง่ายที่สุดในการทำความเข้าใจคือการยกตัวอย่าง
สมมติว่าเรามีโฟลเดอร์ที่มีไฟล์ดังต่อไปนี้
กลาวา01, กลาวา02, กลาวา03, กลาวา04, กลาวา05, กลาวา15, กลาวา17
ลองใช้เทมเพลต Glava0* และรับรายการ Glava01, Glava02, Glava03, Glava04, Glava05
ลองใช้เทมเพลต Glava?5 และรับรายการ Glava05, Glava15
ลองใช้เทมเพลต Glava?(4,5) และรับรายการ Glava04, Glava05, Glava15
ลองใช้เทมเพลต Glava0 และรับรายการ Glava01, Glava02, Glava03
การดำเนินการนิพจน์ทางคณิตศาสตร์
ใช่ bash ก็สามารถทำเช่นนั้นได้เช่นกัน มีสองรูปแบบสำหรับสิ่งนี้
$[การแสดงออก] แรก
$ ที่สอง ((นิพจน์))
ตัวอย่างเช่น
$เอคโค$
ผลลัพธ์ของการดำเนินการจะเป็นหมายเลข 6 หากนิพจน์ไม่ถูกต้อง bash จะแสดงข้อความแสดงข้อผิดพลาด
การทดแทนคำสั่ง
การทดแทนคำสั่งเป็นอย่างมาก เครื่องมืออันทรงพลังทุบตี. ประเด็นก็คือคำสั่งที่เขียนจะเปลี่ยนไปตามผลลัพธ์ของการดำเนินการ แบบฟอร์มบันทึกมีสองแบบ
$(command) และ `command` (ในกรณีนี้ จะไม่ใช้เครื่องหมายคำพูดเดี่ยว แต่เป็นอักขระที่ได้รับจากการผสม SHIFT+~) ตัวอย่างเช่นที่นี่ ตัวอย่างที่ส่องแสงซึ่งใช้ใน Debian เมื่อติดตั้งแพ็คเกจส่วนหัวสำหรับเคอร์เนลปัจจุบัน
# apt-get ติดตั้ง linux-headers-`uname -r`
เมื่อดำเนินการคำสั่ง uname -r จะแสดงเวอร์ชันของเคอร์เนลที่ใช้งาน คือว่าพอผมรันมันก็เปลี่ยนเป็น
# apt-get ติดตั้ง linux-headers-2.6.25-2-686
ยิ่งไปกว่านั้น มันอาจทำให้คุณดูแตกต่างออกไป คุณยังสามารถเปลี่ยนเคอร์เนลและติดตั้งแพ็คเกจด้วยคำสั่งเดียวกันได้
ตัวกรอง
คำสั่งเหล่านี้เป็นคำสั่งที่สามารถเปลี่ยนกระแสข้อมูลอินพุตและส่งออกผลลัพธ์เป็นเอาต์พุตมาตรฐาน
คำอธิบายโดยย่อของทีม
cat ไปยังเอาต์พุตมาตรฐาน (เช่น
บนหน้าจอ) เนื้อหาของไฟล์ที่ระบุ (หรือหลายไฟล์) จะปรากฏขึ้น
จับถ้าชื่อของพวกเขาถูกระบุตามลำดับเป็นอาร์กิวเมนต์คำสั่ง)
grep, fgrep, egrep ค้นหาใน ไฟล์อินพุตหรือข้อมูลจาก อินพุตมาตรฐานบรรทัดที่มีรูปแบบที่ระบุและพิมพ์ไปยังเอาต์พุตมาตรฐาน
tr แทนที่อักขระที่เกิดขึ้นทั้งหมดในสตรีมอินพุตที่แสดงอยู่ในรายการที่กำหนดด้วยอักขระที่สอดคล้องกันจากรายการที่สองที่ระบุ
comm เปรียบเทียบสองไฟล์ทีละบรรทัดและส่งออก 3 คอลัมน์กับเอาต์พุตมาตรฐาน: บรรทัดแรกที่เกิดขึ้นในไฟล์ที่ 1 เท่านั้น บรรทัดที่สองที่เกิดขึ้นในไฟล์ที่ 2 เท่านั้น และบรรทัดที่สามที่ปรากฏในทั้งสองไฟล์
pr รูปแบบการพิมพ์ ไฟล์ข้อความหรือเนื้อหาของอินพุตมาตรฐาน
sed ตัวแก้ไขสตริงที่ใช้ในการแปลงข้อมูลอินพุต (นำมาจากไฟล์หรือจากอินพุตมาตรฐาน)
มากขึ้นเรื่อยๆ แสดงเนื้อหาของไฟล์บนหน้าจอในหน้าแยกตามขนาดของหน้าจอทั้งหมด
wc นับจำนวนคำ บรรทัด หรือไบต์ในสตรีม
ตัวอย่างเช่น,
$ grep CONFIG_XEN -Rl | xargs -i sed -i -e "s/CONFIG_XEN/CONFIG_LUPO/g" ()
ค้นหาไฟล์ใน โฟลเดอร์ปัจจุบันซึ่งมีบรรทัด “CONFIG_XEN” และเปลี่ยนเป็น “CONFIG_LUPO” ในไฟล์ที่พบทั้งหมด
นี่คือที่ที่เราจะหยุดพักเพื่อทำความเข้าใจปริมาณวัสดุทั้งหมด Bash เป็นล่ามที่ทรงพลังมากและต้องฝึกฝนจึงจะเชี่ยวชาญ บทความถัดไปจะกล่าวถึงการสร้างสคริปต์ให้ มาเริ่มเขียนโปรแกรมกัน จนกว่าจะถึงครั้งต่อไป!
แท็ก: ลินุกซ์, บทความ

แท็ก: เหตุใดคุณจึงต้องมีไพพ์ไลน์คำสั่งใน bash?

เมื่อคุณทำงานเป็นทีม คุณจะเลี้ยงดูกันและกันด้วยอารมณ์ งาน ความสำเร็จ และความสำเร็จ....

คำสั่ง /ทีมกระดานคะแนน เพิ่มชื่อ /รายชื่อทีมกระดานคะแนน /ทีมกระดานคะแนนเข้าร่วมชื่อ /ทีมกระดานคะแนนออก ...

google.com/bin/echo foo | grep บาร์" .... getpid() = 13726<– PID ..... 1 · Почему в Ubuntu 16.04 медленный apt-get dist-upgrade? ... Спасибо, очень интересная статься… но как всегда нужна мера, чтобы не полочалось такого:

25 ก.พ. 2552 - ทำตามคำสั่งเสร็จสิ้น ลองดูตัวอย่างเล็กๆ น้อยๆ: #!/bin/bash .... ไปป์ไลน์เป็นเครื่องมือที่ทรงพลังมากสำหรับการทำงานกับคอนโซล Bash .... เพื่อทำบางสิ่งและพยายามทำความเข้าใจว่าทำไมไม่พบโปรแกรมที่ต้องทำไดเร็กทอรี... ... อาจจำเป็นต้องมีการตั้งค่าบางอย่าง แต่ในขณะเดียวกันฉันก็มี...

โปรดช่วยฉันแก้ไขปัญหาเล็กน้อย #!/bin/bash | ผู้เขียนหัวข้อ: อิลยา

30. สร้างไปป์ไลน์เพื่อแสดงเฉพาะชื่อและการอนุญาตของไฟล์ที่อยู่ในไดเร็กทอรีการทำงานของคุณในปัจจุบัน 31. เปลี่ยนไปป์ไลน์ที่สร้างขึ้นเพื่อให้รายการถูกบันทึกในไฟล์ spisok ของไดเร็กทอรี HOME ของคุณ และแสดงเฉพาะจำนวนไฟล์ในรายการเท่านั้น 32. แสดงเนื้อหาของไฟล์ /etc/passwd ซึ่งจัดเรียงตามช่องชื่อผู้ใช้ 33. สร้างนามแฝงที่เรียกว่า loggedon ซึ่งจะแสดงรายการตามลำดับตัวอักษรของผู้ใช้ที่เข้าสู่ระบบ 34. กำหนดชื่อเข้าสู่ระบบให้กับตัวแปร IAM เปิดตัวเชลล์อื่น คุณเห็นตัวแปรนี้หรือไม่? คุณต้องทำอะไรเพื่อดูมันในเชลล์ที่สร้างขึ้น? เปลี่ยนค่าของตัวแปร IAM ในเชลล์ที่สร้าง ออกจากเปลือกที่เกิด ค้นหาค่าของตัวแปรนี้ในซอร์สเชลล์ อธิบายผลลัพธ์ 40. เขียนโปรแกรมเชลล์สวัสดีที่ให้การตอบสนองต่ออาร์กิวเมนต์บรรทัดคำสั่งต่อไปนี้: - อาร์กิวเมนต์ "-d" - โปรแกรมจะดำเนินการคำสั่ง date; - อาร์กิวเมนต์ "-l" - โปรแกรมจะแสดงเนื้อหาของไดเร็กทอรีปัจจุบัน หากไม่มีข้อโต้แย้งหรือข้อโต้แย้งที่ไม่ถูกต้องในบรรทัดคำสั่ง โปรแกรมจะพิมพ์วิธีใช้เกี่ยวกับตัวเลือกต่างๆ 41. เขียนโปรแกรมคำศัพท์ที่จะให้ผู้ใช้ป้อนทีละคำจนกระทั่งเขาเข้าสู่คำว่า "จบ" จำทุกคำที่คุณป้อน หลังจากป้อนคำว่า "end" แล้ว ให้แสดงคำที่ป้อนทั้งหมด ขอบคุณหากคุณสามารถแนะนำอย่างน้อยหนึ่งรายการเหล่านี้

Vitaly  32. cat /etc/passwd | เรียงลำดับ

คู่มือการเขียนสคริปต์ Bash ขั้นสูง - Linux ในภาษารัสเซีย

เหตุใดความรู้เกี่ยวกับภาษาเชลล์จึงมีความจำเป็น? 2. ..... การถ่ายโอนเอาต์พุตจากคำสั่ง echo ไปยังคำสั่ง read ตามแนวไปป์ไลน์ 33-1. สคริปต์ตัวตัดคำ; 33-2. มากกว่า...

การเปลี่ยนเส้นทาง I/O - OpenNet

คู่มือ Bash-Scripting ขั้นสูง: ศิลปะแห่งการเขียนโปรแกรมภาษา... คำสั่งการเปลี่ยนเส้นทางบรรทัดเดียว # (มีผลเฉพาะบรรทัด... เฉพาะ stderr เท่านั้นที่ถูกไพพ์ exec 3>&1 # บันทึกปัจจุบัน...

ตัวดำเนินการ for-in มีไว้สำหรับการเข้าถึงค่าที่แสดงอยู่ในรายการตามลำดับ แต่ละค่าในรายการตามลำดับจะถูกกำหนดให้กับตัวแปร ไวยากรณ์มีดังนี้:

สำหรับตัวแปรใน value_list ให้ทำคำสั่งเสร็จสิ้น

ลองดูตัวอย่างเล็กๆ น้อยๆ:

#!/bin/bash สำหรับฉันใน 0 1 2 3 4 #เราจะสลับกันกำหนดค่าตั้งแต่ 0 ถึง 4 รวมให้กับตัวแปร $iทำเสียงสะท้อน "หมายเลขคอนโซลคือ $ฉัน ">> /dev/pts/$i #เขียนบรรทัด "หมายเลขคอนโซลคือ $i" ลงในไฟล์ /dev/pts/$i (ไฟล์เทอร์มินัลเสมือน)เสร็จสิ้น #loop เสร็จสิ้น ทางออก 0

หลังจากรันตัวอย่างแล้ว บรรทัดที่มีหมายเลขจะปรากฏในคอนโซลเสมือน 5 ตัวแรก (เทอร์มินัล) ตัวแปร $i จะถูกแทนที่ด้วยค่าจากรายการและในลูปสลับกัน อยู่ระหว่างดำเนินการด้วยค่าของตัวแปรนี้

รอบ ในขณะที่วนซ้ำ

การวนซ้ำ while นั้นซับซ้อนกว่าการวนซ้ำ for-in และใช้เพื่อทำซ้ำคำสั่งตราบใดที่นิพจน์บางส่วนเป็นจริง (โค้ดส่งคืน = 0) ไวยากรณ์ของตัวดำเนินการมีดังนี้:

ในขณะที่นิพจน์หรือคำสั่งส่งคืนโค้ดส่งคืนของคำสั่ง do เสร็จแล้ว

ลองดูตัวอย่างการทำงานของลูปต่อไปนี้:

#!/bin/bash อีกครั้ง = ใช่ #กำหนดค่า "ใช่" ให้กับตัวแปรอีกครั้งในขณะที่ [" $อีกครั้ง"= "ใช่" ] #เราจะวนซ้ำจนกว่า $อีกครั้ง เท่ากับ "ใช่"ทำ echo "กรุณาใส่ชื่อ:" อ่านชื่อ echo "ชื่อที่คุณป้อนคือ $name" echo "คุณต้องการดำเนินการต่อหรือไม่?" อ่านใหม่เสร็จแล้วก็ echo "Bye-Bye"

และตอนนี้ผลลัพธ์ของสคริปต์:

Ite@ite-desktop:~$ ./bash2_primer1.sh โปรดป้อนชื่อ: ite ชื่อที่คุณป้อนคือ ite คุณต้องการดำเนินการต่อหรือไม่? ใช่ กรุณากรอกชื่อ: mihail ชื่อที่คุณป้อนคือ mihail คุณต้องการดำเนินการต่อหรือไม่? ไม่ ลาก่อน

อย่างที่คุณเห็น การวนซ้ำจะทำงานจนกว่าเราจะป้อนอย่างอื่นที่ไม่ใช่ "ใช่" ระหว่าง do และ Done คุณสามารถอธิบายโครงสร้าง โอเปอเรเตอร์ ฯลฯ ทั้งหมดได้จะถูกดำเนินการในลูป แต่คุณควรระวังกับการวนซ้ำนี้ หากคุณรันคำสั่งใดๆ ในนั้นโดยไม่เปลี่ยนตัวแปรนิพจน์ คุณก็จะได้รับ ติดอยู่ในวงวนไม่มีที่สิ้นสุด

ตอนนี้เกี่ยวกับเงื่อนไขความจริง หลังจากผ่านไประยะหนึ่ง เช่นเดียวกับในคำสั่งแบบมีเงื่อนไข if-then-else คุณสามารถแทรกนิพจน์หรือคำสั่งใดๆ ที่ส่งคืนโค้ดส่งคืนได้ และลูปจะถูกดำเนินการจนกว่าโค้ดส่งคืน = 0! โอเปอเรเตอร์ "[" เป็นแบบอะนาล็อกของคำสั่ง test ซึ่งจะตรวจสอบความจริงของเงื่อนไขที่ถูกส่งไป

ลองดูอีกตัวอย่างหนึ่ง ฉันเอามาจากหนังสือ Advanced Bash scripting ฉันชอบมันมาก ยิ้ม แต่ฉันทำให้มันง่ายขึ้นเล็กน้อย ในตัวอย่างนี้ เราจะแนะนำการวนซ้ำ UNTIL-DO อีกประเภทหนึ่ง อันนี้ใช้ได้จริง อะนาล็อกที่สมบูรณ์ วงจรในขณะที่ทำดำเนินการเฉพาะในขณะที่นิพจน์บางส่วนเป็นเท็จเท่านั้น

นี่คือตัวอย่าง:

#!/bin/bash echo "ป้อนตัวเศษ:"อ่านเงินปันผลสะท้อน "ป้อนตัวส่วน: "อ่านตัวหาร dnd =$เงินปันผล #เราจะเปลี่ยนตัวแปรเงินปันผลและตัวหาร #มาเก็บความรู้ไว้ในตัวแปรอื่นๆ กันดีกว่า เพราะ... พวกเขาให้เรา#จะต้องการ dvs =$divisor ส่วนที่เหลือ =1 จนถึง [ " $ส่วนที่เหลือ "-eq 0 ] ให้ “ส่วนที่เหลือ = ตัวหาร % เงินปันผล”เงินปันผล =$ตัวหาร ตัวหาร =$ส่วนที่เหลือ เสร็จแล้ว echo "GCD ของตัวเลข $dnd และ $dvs = $เงินปันผล "

ผลลัพธ์ของการดำเนินการสคริปต์:

Ite@ite-desktop:~$ ./bash2_primer3.sh ป้อนตัวเศษ: 100 ป้อนตัวส่วน: 90 GCD ของ 100 และ 90 = 10

การดำเนินการทางคณิตศาสตร์

ปล่อยให้คำสั่ง

คำสั่งให้สร้าง การดำเนินการทางคณิตศาสตร์มากกว่าตัวเลขและตัวแปร

ลองดูตัวอย่างเล็ก ๆ ที่เราคำนวณตัวเลขที่ป้อน:

#!/bin/bash echo "ป้อน a: " อ่าน echo "ป้อน b: " อ่าน b ให้ "c = a + b" #addition echo "a+b= $ซี"ให้ "c = a / b" #division echo "a/b= $ซี"ให้ "ค<<= 2" #เลื่อน c ไปทางซ้าย 2 บิตเสียงสะท้อน "c หลังจากกะไป 2 บิต: $c "ให้ "c = a % b" #หาเศษที่เหลือหารด้วยbเสียงสะท้อน " $a / $b . ส่วนที่เหลือ: $c "

ผลการดำเนินการ:

Ite@ite-desktop:~$ ./bash2_primer2.sh ป้อน a: 123 ป้อน b: 12 a+b= 135 a/b= 10 c หลังจาก shift ด้วย 2 หลัก: 40 123 / 12. ส่วนที่เหลือ: 3

อย่างที่คุณเห็นไม่มีอะไรซับซ้อน รายการการดำเนินการทางคณิตศาสตร์เป็นมาตรฐาน:

ส่วนที่เพิ่มเข้าไป
- - การลบ
* - การคูณ
/ - แผนก
** - การยกกำลัง
% - โมดูลัส (การหารแบบโมดูโล) ส่วนที่เหลือของการหาร

ให้ อนุญาตให้คุณใช้คำย่อสำหรับคำสั่งทางคณิตศาสตร์ ซึ่งจะช่วยลดจำนวนตัวแปรที่ใช้

ตัวอย่างเช่น: a = a+b เทียบเท่ากับ a +=b เป็นต้น

การทำงานกับโปรแกรมภายนอกเมื่อเขียนเชลล์สคริปต์

ประการแรก ทฤษฎีที่เป็นประโยชน์บางประการ

การเปลี่ยนเส้นทางสตรีม

Bash (เช่นเดียวกับเชลล์อื่น ๆ ) มีตัวอธิบายไฟล์ในตัว: 0 (stdin), 1 (stdout), 2 (stderr)

stdout - เอาต์พุตมาตรฐาน ทุกสิ่งที่โปรแกรมส่งออกไปที่นี่
stdin - อินพุตมาตรฐาน นี่คือทั้งหมดที่ผู้ใช้พิมพ์ในคอนโซล
stderr - เอาต์พุตข้อผิดพลาดมาตรฐาน

สำหรับการดำเนินการกับจุดจับเหล่านี้ จะมีอักขระพิเศษ: > (การเปลี่ยนเส้นทางเอาต์พุต)< (перенаправление ввода). Оперировать ими не сложно. Например:

cat /dev/random > /dev/null

เปลี่ยนเส้นทางเอาต์พุตของ cat /dev/random ไปที่ /dev/null (การดำเนินการที่ไม่มีประโยชน์โดยสิ้นเชิง) หรือ

ls -la > รายการ

เขียนเนื้อหาของไดเร็กทอรีปัจจุบันลงในไฟล์รายการ (มีประโยชน์มากกว่า)

หากจำเป็นต้องต่อท้ายไฟล์ (เมื่อใช้ ">" ไฟล์จะถูกแทนที่) คุณต้องใช้ ">>" แทน ">"

ซูโดะ< my_password

หลังจากถามรหัสผ่าน sudo มันจะถูกนำมาจากไฟล์ my_password ราวกับว่าคุณป้อนจากคีย์บอร์ด

หากคุณต้องการเขียนเฉพาะข้อผิดพลาดที่อาจเกิดขึ้นขณะรันโปรแกรมลงในไฟล์ คุณสามารถใช้:

./ program_with_error 2 > error_file

หมายเลข 2 ก่อน ">" หมายความว่าคุณต้องเปลี่ยนเส้นทางทุกสิ่งที่ลงท้ายด้วย descriptor 2 (stderr)

หากคุณต้องการบังคับให้ stderr เขียนถึง stdout ก็สามารถทำได้ดังนี้ ทาง:

./ program_with_error 2 >& 1

สัญลักษณ์ "&" หมายถึงตัวชี้ไปยัง descriptor 1(stdout)

(ตามค่าเริ่มต้น stderr จะเขียนไปยังคอนโซลที่ผู้ใช้กำลังทำงานอยู่ (หรือเขียนไปที่จอแสดงผล))

2. สายพานลำเลียง

ไปป์ไลน์เป็นเครื่องมือที่ทรงพลังมากสำหรับการทำงานกับคอนโซล Bash ไวยากรณ์นั้นง่าย:

ทีม1 | คำสั่ง 2 - หมายความว่าเอาต์พุตของคำสั่ง 1 จะถูกส่งผ่านเป็นอินพุตไปยังคำสั่ง 2

ไปป์ไลน์สามารถจัดกลุ่มเป็นลูกโซ่และส่งออกโดยใช้การเปลี่ยนเส้นทางไปยังไฟล์ ตัวอย่างเช่น:

ls -la | grep "แฮช" | เรียงลำดับ > sortilg_list

เอาต์พุตของคำสั่ง ls -la จะถูกส่งผ่านไปยังคำสั่ง grep ซึ่งเลือกบรรทัดทั้งหมดที่มีคำว่า hash และส่งผ่านไปยังคำสั่ง sort ซึ่งเขียนผลลัพธ์ลงในไฟล์ sorting_list ทุกอย่างค่อนข้างชัดเจนและเรียบง่าย

บ่อยครั้งที่สคริปต์ Bash ถูกใช้เพื่อทำให้การดำเนินการตามปกติในคอนโซลเป็นไปโดยอัตโนมัติ ดังนั้นบางครั้งจึงจำเป็นต้องประมวลผล stdout ของคำสั่งหนึ่งและถ่ายโอนไปยัง stdin ไปยังคำสั่งอื่น ในขณะที่ผลลัพธ์ของการดำเนินการคำสั่งเดียวจะต้องได้รับการประมวลผลในบางส่วน ทาง. ในส่วนนี้ ฉันจะพยายามอธิบายหลักการพื้นฐานของการทำงานกับคำสั่งภายนอกภายในสคริปต์ ฉันคิดว่าฉันได้ยกตัวอย่างมาเพียงพอแล้วและตอนนี้ฉันสามารถเขียนได้เฉพาะประเด็นหลักเท่านั้น

1. การส่งผ่านเอาต์พุตไปยังตัวแปร

หากต้องการบันทึกเอาต์พุตของคำสั่งลงในตัวแปร เพียงใส่คำสั่งด้วยเครื่องหมายคำพูด `` เป็นต้น

A = ` เอคโค "qwerty" ` เอคโค $a

ผลลัพธ์: qwerty

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

LIST =` ค้นหา / svn/ -type d 2>/ dev/ null| awk "(FS="/") (พิมพ์ $4)" | เรียงลำดับ | ยูนิค | tr "\n" " " ` สำหรับ ONE_OF_LIST ใน $LIST ทำ svnadmin hotcopy / svn/ $ONE_OF_LIST / svn/ temp4backup/ $ONE_OF_LIST เสร็จแล้ว

ที่นี่เราใช้ สำหรับวง-do-done เพื่อเก็บถาวรไดเร็กทอรีทั้งหมดในโฟลเดอร์ /svn/ โดยใช้คำสั่ง svnadmin hotcopy (ซึ่งในกรณีของเราไม่สำคัญกับใครเลย ตามตัวอย่าง) บรรทัดที่น่าสนใจที่สุดคือ: LIST=`find /svn/ -type d 2>/dev/null| awk "(FS="/") (พิมพ์ $4)"| เรียงลำดับ|uniq | tr "\n" " "` ในนั้น ตัวแปร LIST ได้รับการกำหนดการดำเนินการของคำสั่ง find ซึ่งประมวลผลโดยคำสั่ง awk, sort, uniq, tr (เราจะไม่พิจารณาคำสั่งเหล่านี้ทั้งหมด เนื่องจากนี่เป็นบทความแยกต่างหาก) . ตัวแปร LIST จะมีชื่อของไดเร็กทอรีทั้งหมดในโฟลเดอร์ /svn/ ที่อยู่ในหนึ่งบรรทัด (เพื่อป้อนเข้าสู่วงจร

อย่างที่คุณเห็นทุกอย่างไม่ยากเพียงแค่เข้าใจหลักการและเขียนสคริปต์ของคุณเองสองสามตัว โดยสรุปของบทความนี้ ฉันขอให้คุณโชคดีในการเรียนรู้ BASH และ Linux โดยทั่วไป ยินดีต้อนรับการวิจารณ์ตามปกติ บทความถัดไปอาจจะเกี่ยวกับการใช้โปรแกรมเช่น sed, awk

สิ่งที่จำเป็น?

คุณควรทำความคุ้นเคยกับบรรทัดคำสั่งและแนวคิดการเขียนโปรแกรมพื้นฐาน แม้ว่านี่จะไม่ใช่บทช่วยสอนการเขียนโปรแกรม แต่ก็อธิบาย (หรือเช่น อย่างน้อยพยายามอธิบาย) แนวคิดพื้นฐานหลายประการ
การใช้เอกสารนี้

เอกสารนี้อาจจำเป็นในสถานการณ์ต่อไปนี้:

คุณมีแนวคิดเกี่ยวกับการเขียนโปรแกรม และจำเป็นต้องดำเนินกระบวนการเขียนโค้ดเชลล์สคริปต์บางตัว

แนวคิดในการเขียนโปรแกรมของคุณไม่เฉพาะเจาะจงเพียงพอและต้องการคำแนะนำเพิ่มเติม

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

คุณกำลังย้ายจาก DOS/Windows (หรือได้ดำเนินการไปแล้ว) และต้องการสร้างไฟล์ "ชุด"

คุณเป็นคนเนิร์ดและอ่านวิธีทำต่างๆ ที่เกี่ยวข้อง

สคริปต์ที่ง่ายที่สุด

HOW-TO นี้พยายามให้แนวทางบางประการสำหรับการเขียนโปรแกรมเชลล์ตามตัวอย่างเท่านั้น

ในส่วนนี้คุณจะพบกับสคริปต์เล็กๆ น้อยๆ ที่อาจเป็นประโยชน์กับคุณเมื่อเชี่ยวชาญเทคนิคบางอย่าง

สคริปต์ "สวัสดีชาวโลก" แบบดั้งเดิม

#!/bin/bash echo สวัสดีชาวโลก!

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

บรรทัดที่สองเป็นการดำเนินการเดียวที่สคริปต์นี้ดำเนินการ โดยพิมพ์ "Hello world" ไปยังเทอร์มินัล

หากคุณได้รับข้อความเช่น ./hello.sh: ไม่พบคำสั่ง บางทีบรรทัดแรก "#!/bin/bash" อาจผิด เรียกใช้ Whereis bash หรือดูการค้นหา bash เพื่อดูว่าบรรทัดนี้ควรเป็นอย่างไร

สคริปต์สำรองข้อมูลอย่างง่าย

#!/bin/bash
tar -cZf /var/my-backup.tgz /home/me/

ในสคริปต์นี้ แทนที่จะพิมพ์ข้อความบนเทอร์มินัล เราสร้างไฟล์เก็บถาวร tar ของโฮมไดเร็กทอรีของผู้ใช้ สคริปต์นี้ไม่ได้มีไว้สำหรับการใช้งานจริง สคริปต์ที่มีประสิทธิภาพมากขึ้นจะถูกนำเสนอในภายหลังในเอกสารนี้ สำเนาสำรอง.

ทั้งหมดเกี่ยวกับทฤษฎีการเปลี่ยนเส้นทางและมุมมองด่วน

ตัวอธิบายไฟล์มี 3 ตัว: stdin - อินพุตมาตรฐาน, stdout - เอาต์พุตมาตรฐาน และ stderr - ข้อผิดพลาดมาตรฐาน

คุณสมบัติหลักของคุณ:
เปลี่ยนเส้นทาง stdout ไปยังไฟล์
เปลี่ยนเส้นทาง stderr ไปยังไฟล์
เปลี่ยนเส้นทาง stdout ไปที่ stderr
เปลี่ยนเส้นทาง stderr ไปที่ stdout
เปลี่ยนเส้นทาง stderr และ stdout ไปยังไฟล์
เปลี่ยนเส้นทาง stderr และ stdout ไปที่ stdout
เปลี่ยนเส้นทาง stderr และ stdout ไปที่ stderr

1 หมายถึง stdout และ 2 หมายถึง stderr หมายเหตุสั้นๆ เพื่อความเข้าใจเพิ่มเติม: ด้วยคำสั่ง less คุณสามารถดูทั้ง stdout ซึ่งยังคงอยู่ในบัฟเฟอร์ และ stderr ซึ่งพิมพ์ลงบนหน้าจอ อย่างไรก็ตาม จะถูกลบออกเมื่อคุณพยายาม "เรียกดู" บัฟเฟอร์

ตัวอย่าง: stdout เป็นไฟล์

การดำเนินการนี้จะเขียนเอาต์พุตมาตรฐานของโปรแกรมลงในไฟล์

ls -l > ls-l.txt

สิ่งนี้จะสร้างไฟล์ชื่อ "ls-l.txt" มันจะมีทุกสิ่งที่คุณจะเห็นหากคุณเพียงแค่รันคำสั่ง "ls -l" 3.3 ตัวอย่าง: stderr ไปยังไฟล์
การดำเนินการนี้จะเขียนสตรีมข้อผิดพลาดมาตรฐานของโปรแกรมลงในไฟล์
grep ดา * 2> grep-errors.txt

สิ่งนี้จะสร้างไฟล์ชื่อ "grep-errors.txt" ซึ่งจะมีส่วนข้อผิดพลาดมาตรฐานของเอาต์พุตคำสั่ง "grep;da;*" 3.4 ตัวอย่าง: stdout ถึง stderr

การดำเนินการนี้จะเขียนเอาต์พุตมาตรฐานของโปรแกรมลงในไฟล์เดียวกันกับสตรีมข้อผิดพลาดมาตรฐาน
grep ดา * 1>&2

ที่นี่เอาต์พุตมาตรฐานของคำสั่งจะถูกส่งไปยังข้อผิดพลาดมาตรฐาน คุณสามารถเห็นสิ่งนี้ได้หลายวิธี 3.5 ตัวอย่าง: stderr 2 stdout

การดำเนินการนี้จะเขียนสตรีมข้อผิดพลาดมาตรฐานของโปรแกรมไปยังตำแหน่งเดียวกับเอาต์พุตมาตรฐาน
grep * 2>&1
ที่นี่สตรีมข้อผิดพลาดมาตรฐานของคำสั่งจะถูกส่งไปยังเอาต์พุตมาตรฐาน หากคุณไพพ์ผลลัพธ์ (|) ให้น้อยลง คุณจะเห็นว่าบรรทัดที่ปกติจะหายไป (ตามที่เขียนไปยังข้อผิดพลาดมาตรฐาน) จะถูกบันทึกไว้ในกรณีนี้ (เนื่องจากบรรทัดเหล่านั้นอยู่ในเอาต์พุตมาตรฐาน) 3.6 ตัวอย่าง: stderr และ stdout ที่จะบันทึกไฟล์

การกระทำนี้จะทำให้เอาท์พุตของโปรแกรมทั้งหมดอยู่ในไฟล์ นี่เป็นตัวเลือกที่ดีสำหรับงาน cron: หากคุณต้องการให้คำสั่งทำงานแบบเงียบๆ
rm -f $(ค้นหา / -name core) &> /dev/null

สิ่งนี้ (สมมติว่าเป็น cron) จะลบไฟล์ใด ๆ ที่เรียกว่า "core" ในไดเรกทอรีใด ๆ โปรดจำไว้ว่าคุณควรแน่ใจอย่างสมบูรณ์ว่าคำสั่งทำอะไรถ้าคุณต้องการเขียนทับเอาต์พุต 4. สายพานลำเลียง

เนื้อหาในส่วนนี้จะอธิบายวิธีที่ค่อนข้างง่ายและใช้งานได้จริงว่าควรใช้สายพานลำเลียงอย่างไร และเหตุใดคุณจึงต้องใช้สายพานลำเลียง
มันคืออะไรและทำไมคุณจึงควรใช้มัน?

ไปป์ไลน์ช่วยให้คุณสามารถใช้งาน (ผู้เขียนเชื่อว่านี่ค่อนข้างง่าย) เอาต์พุตของโปรแกรมหนึ่งเป็นอินพุตของอีกโปรแกรมหนึ่ง

ตัวอย่าง: ไปป์ไลน์อย่างง่ายด้วย sed

นี่เป็นวิธีง่ายๆ ในการใช้สายพานลำเลียง

ls -l | sed -e "s//u/g"

สิ่งที่เกิดขึ้นที่นี่คือคำสั่ง ls;-l จะถูกดำเนินการในขั้นต้น และเอาต์พุตจะถูกส่งไปยังโปรแกรม sed แทนที่จะแสดงบนหน้าจอ ซึ่งจะพิมพ์สิ่งที่ควรปรากฏบนหน้าจอ 4.3 ตัวอย่าง: ทางเลือกสำหรับ ls;-l;*.txt

สิ่งนี้อาจซับซ้อนกว่า ls;-l;*.txt อย่างมาก แต่นำเสนอไว้ที่นี่เพียงเพื่อแสดงตัวอย่างการทำงานกับไปป์ไลน์เท่านั้น ไม่ใช่เพื่อตัดสินใจระหว่างสองวิธีในการแสดงรายการ

ls -l | grep "\.txt$"

ที่นี่ เอาต์พุตของ ls -l จะถูกส่งไปยัง grep ซึ่งจะพิมพ์บรรทัดที่ตรงกับนิพจน์ทั่วไป "\.txt$" 5. ตัวแปร

คุณสามารถใช้ตัวแปรในลักษณะเดียวกับในภาษาการเขียนโปรแกรมใดๆ ไม่มีประเภทข้อมูล ตัวแปรใน bash อาจเป็นตัวเลข อักขระ หรือสตริงอักขระก็ได้

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

ตัวอย่าง: "Hello World!" โดยใช้ตัวแปร

#!/bin/bash
STR="สวัสดีชาวโลก!"
เสียงสะท้อน $STR

บรรทัดที่สองสร้างตัวแปรชื่อ STR และกำหนดค่าสตริง "Hello World!" ให้กับตัวแปร จากนั้นแยกค่า VALUE ของตัวแปรนี้ออกโดยการเพิ่มเครื่องหมาย "$" นำหน้า โปรดจำไว้ว่า (พยายามอย่างหนัก) ว่าถ้าคุณไม่ใช้เครื่องหมาย "$" ผลลัพธ์ของโปรแกรมอาจแตกต่างกัน อาจไม่ใช่สิ่งที่คุณต้องการ
ตัวอย่าง: สคริปต์สำรองข้อมูลที่ง่ายมาก (มีประสิทธิภาพมากกว่า)
#!/bin/bash
OF=/var/my-backup-$(date +%Y%m%d).tgz #OF - ไฟล์เอาท์พุต - ไฟล์เอาท์พุต
tar -cZf $OF /home/me/

สคริปต์นี้แนะนำแนวคิดอื่น ก่อนอื่นคุณควรจัดการกับบรรทัดที่สอง ให้ความสนใจกับนิพจน์ "$(date +%Y%m%d)" หากคุณเรียกใช้สคริปต์นี้ คุณจะสังเกตเห็นว่าสคริปต์ดำเนินการคำสั่งภายในวงเล็บ โดยขัดขวางเอาต์พุตของสคริปต์

โปรดทราบว่าในสคริปต์นี้ ชื่อไฟล์เอาต์พุตจะเปลี่ยนทุกวันตามรูปแบบของวันที่ (+%Y%m%d) คีย์คำสั่ง คุณสามารถแทนที่สิ่งนี้ด้วยการกำหนดรูปแบบอื่นได้
ตัวอย่างอื่นๆ:
เสียงสะท้อน LS
เสียงสะท้อน $(ls)

ตัวแปรท้องถิ่น

ตัวแปรท้องถิ่นสามารถสร้างขึ้นได้โดยใช้คำสำคัญท้องถิ่น
#!/bin/bash
สวัสดี=สวัสดี
ฟังก์ชั่นสวัสดี (
ท้องถิ่น HELLO=World
สะท้อน $สวัสดี
}
สะท้อน $สวัสดี
สวัสดี
สะท้อน $สวัสดี
ตัวอย่างนี้ควรจะเพียงพอที่จะแสดงให้เห็นว่าตัวแปรท้องถิ่นสามารถนำมาใช้อย่างไร

คำสั่งแบบมีเงื่อนไข

ข้อความที่มีเงื่อนไขช่วยให้คุณสามารถตัดสินใจว่าจะดำเนินการหรือไม่ การตัดสินใจเกิดขึ้นเมื่อคำนวณค่าของนิพจน์

แค่ทฤษฎี

ประโยคเงื่อนไขมีหลายรูปแบบ รูปแบบเบื้องต้นคือนิพจน์ if then โดยที่ "คำสั่ง" จะถูกดำเนินการก็ต่อเมื่อ "นิพจน์" ประเมินว่าเป็น "จริง" "2<1" - это выражение, имеющее значение "ложь", в то время как "2>1" - "จริง"

มีรูปแบบอื่นๆ ของคำสั่งแบบมีเงื่อนไข เช่น if expression แล้วก็คำสั่ง 1 else คำสั่ง 2 ในที่นี้ "operator1" จะถูกดำเนินการหาก "expression" เป็นจริง มิฉะนั้น "คำสั่ง 2" จะถูกดำเนินการ

คำสั่งแบบมีเงื่อนไขอีกรูปแบบหนึ่งคือ: ถ้า expression1 แล้วตัวดำเนินการ 1 อื่น ๆ ถ้านิพจน์ 2 แล้วก็ตัวดำเนินการ 2 อย่างอื่นตัวดำเนินการ 3 แบบฟอร์มนี้เพิ่มเฉพาะลำดับ "ELSE IF "expression2" THEN "statement2"" เท่านั้น ทำให้มีการดำเนินการ "statement2" หาก "expression2" ประเมินเป็น "true" ทุกสิ่งทุกอย่างสอดคล้องกับแนวคิดของคุณเกี่ยวกับเรื่องนี้ (ดูแบบฟอร์มก่อนหน้า)

คำไม่กี่คำเกี่ยวกับไวยากรณ์:
โครงสร้างพื้นฐานของคำสั่ง "if" ใน bash มีลักษณะดังนี้:
ถ้า [การแสดงออก];
แล้ว
รหัสถ้า "นิพจน์" เป็นจริง
ฟิ

ตัวอย่าง: ตัวอย่างพื้นฐานของคำสั่งแบบมีเงื่อนไข if;..;then
#!/bin/bash
ถ้า ["foo" = "foo" ]; แล้ว

ฟิ

หากนิพจน์ภายในวงเล็บเหลี่ยมเป็นจริง โค้ดที่จะดำเนินการจะอยู่หลังคำว่า "แล้ว" และอยู่หน้าคำว่า "fi" ซึ่งระบุจุดสิ้นสุดของโค้ดที่จะดำเนินการเมื่อตรงตามเงื่อนไข
ตัวอย่าง: ตัวอย่างพื้นฐานของคำสั่งแบบมีเงื่อนไข if;..;then;...;else
#!/bin/bash
ถ้า ["foo" = "foo" ]; แล้ว
การแสดงออกของ echo ประเมินเป็นจริง
อื่น

ฟิ

ตัวอย่าง: คำสั่งแบบมีเงื่อนไขพร้อมตัวแปร
#!/bin/bash
T1="ฟู"
T2="บาร์"
ถ้า [ "$T1" = "$T2" ]; แล้ว
การแสดงออกของ echo ประเมินเป็นจริง
อื่น
นิพจน์ echo ประเมินว่าเป็นเท็จ
ฟิ
สำหรับ, ในขณะที่ และ จนกระทั่ง วนซ้ำ
ในส่วนนี้ คุณจะคุ้นเคยกับลูป for, while และ until
for loop แตกต่างเล็กน้อยจากคู่ในภาษาโปรแกรมอื่นๆ ประการแรก ช่วยให้คุณสามารถดำเนินการตามลำดับกับ "คำ" ในสตริงได้
while loop รันโค้ดชิ้นหนึ่งหากนิพจน์ที่กำลังทดสอบเป็นจริง และหยุดหากเป็นเท็จ (หรือพบการขัดจังหวะลูปที่กำหนดไว้อย่างชัดเจนภายในโค้ดที่รัน)
การวนซ้ำจนกระทั่งเกือบจะเหมือนกับการวนซ้ำ while ข้อแตกต่างเพียงอย่างเดียวคือโค้ดจะถูกดำเนินการหากนิพจน์ที่กำลังทดสอบเป็นเท็จ
หากคุณคิดว่า while และ until มีความคล้ายคลึงกันมาก แสดงว่าคุณคิดถูก

ตัวอย่างสำหรับการวนซ้ำ

#!/bin/bash
สำหรับฉันใน $(ls); ทำ
รายการสะท้อน: $i
เสร็จแล้ว

ในบรรทัดที่สอง เราแสดง i เป็นตัวแปรที่ได้รับค่าต่างๆ ที่มีอยู่ใน $(;ls;)

หากจำเป็น บรรทัดที่สามอาจยาวกว่านี้ หรืออาจมีหลายบรรทัดก่อนทำ (บรรทัดที่ 4)

"done" (บรรทัดที่ 4) บ่งชี้ว่าโค้ดที่ใช้ $i กำลังจะสิ้นสุด และ $i ได้รับค่าใหม่

สคริปต์นี้ไม่ได้ตั้งใจให้มีความสำคัญอย่างยิ่ง การใช้ for loop ที่มีประโยชน์มากกว่าคือใช้เพื่อเลือกเฉพาะไฟล์บางไฟล์ในตัวอย่างก่อนหน้านี้
C-like สำหรับ

fiesh แนะนำให้เพิ่มแบบฟอร์มลูปนี้ นี่คือ for loop ซึ่งคล้ายกับ for loop มากที่สุดใน C, Perl ฯลฯ

#!/bin/bash
สำหรับฉันใน `seq 1 10`;
ทำ
สะท้อน $i
เสร็จแล้ว
ตัวอย่างขณะวนซ้ำ:
#!/bin/bash
ตัวนับ=0
ในขณะที่ [ $COUNTER -lt 10 ]; ทำ
echo ตัวนับคือ $COUNTER
ให้ COUNTER=COUNTER+1
เสร็จแล้ว

สคริปต์นี้ “จำลอง” โครงสร้าง “สำหรับ” ที่รู้จักกันดี (ใน C, Pascal, Perl ฯลฯ)

ตัวอย่างจนกระทั่งวนซ้ำ:

#!/bin/bash
เคาน์เตอร์=20
จนถึง [ $COUNTER -lt 10 ]; ทำ
เสียงสะท้อน COUNTER $ COUNTER
ให้ COUNTER-=1
เสร็จแล้ว

ฟังก์ชั่น

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

การประกาศฟังก์ชันเป็นเพียงรายการฟังก์ชัน my_func ( my_code )

การเรียกใช้ฟังก์ชันจะดำเนินการในลักษณะเดียวกับการเรียกใช้โปรแกรมอื่น คุณเพียงแค่เขียนชื่อของเธอ

ฟังก์ชั่นตัวอย่าง
#!/bin/bash
ออกจากฟังก์ชัน (
ออก
}
ฟังก์ชั่นสวัสดี (
สะท้อน สวัสดี!
}
สวัสดี
ล้มเลิก
เอคโคฟู
บรรทัดที่ 2-4 มีฟังก์ชัน "quit" บรรทัดที่ 5-7 มีฟังก์ชัน "hello" หากคุณไม่เข้าใจกระบวนการที่ทำโดยสคริปต์นี้ ลองดูสิ!

ควรสังเกตว่าไม่จำเป็นต้องประกาศฟังก์ชันในลำดับใดโดยเฉพาะ

หากคุณเรียกใช้สคริปต์ โปรดสังเกตว่าฟังก์ชัน "hello" จะถูกเรียกก่อน จากนั้นจึงเรียกฟังก์ชัน "quit" ส่วนโปรแกรมไม่เคยถึงบรรทัดที่ 10

ตัวอย่างฟังก์ชันพร้อมพารามิเตอร์
#!/bin/bash
ออกจากฟังก์ชัน (
ออก
}
ฟังก์ชัน อี (
สะท้อน $1
}
สวัสดี
อีเวิลด์
ล้มเลิก
เอคโคฟู
สคริปต์นี้เกือบจะเหมือนกับสคริปต์ก่อนหน้า ความแตกต่างที่สำคัญคือฟังก์ชัน "e" มันพิมพ์อาร์กิวเมนต์แรกที่ได้รับ อาร์กิวเมนต์ในฟังก์ชันได้รับการประมวลผลในลักษณะเดียวกับอาร์กิวเมนต์ที่ส่งไปยังสคริปต์

ส่วนต่อประสานกับผู้ใช้

การใช้ Select เพื่อสร้างเมนูง่ายๆ
#!/bin/bash
OPTIONS="สวัสดี เลิก"
เลือกตัวเลือก $OPTIONS; ทำ
ถ้า [ "$opt" = "ออก" ]; แล้ว
เสียงสะท้อนเสร็จแล้ว
ออก
เอลฟ์ [ "$opt" = "สวัสดี" ]; แล้ว
สะท้อนสวัสดีชาวโลก
อื่น
ชัดเจน
สะท้อนตัวเลือกที่ไม่ดี
ฟิ
เสร็จแล้ว
หากคุณเรียกใช้สคริปต์นี้ คุณจะเห็นว่านี่คือความฝันของโปรแกรมเมอร์เกี่ยวกับเมนูแบบข้อความ คุณอาจสังเกตเห็นว่าสิ่งนี้คล้ายกับโครงสร้าง "for" มาก แต่แทนที่จะวนซ้ำแต่ละ "คำ" ใน $OPTIONS โปรแกรมจะสำรวจความคิดเห็นผู้ใช้
การใช้บรรทัดคำสั่ง
#!/bin/bash
ถ้า [ -z "$1" ]; แล้ว
การใช้เสียงสะท้อน: ไดเรกทอรี $0
ออก
ฟิ
SRCD=$1 #SRCD - ไดเรกทอรี SouRCe - ไดเรกทอรีต้นทาง

tar -cZf $TGTD$ของ $SRCD
ควรชัดเจนว่าสคริปต์นี้ทำอะไร นิพจน์ในคำสั่งเงื่อนไขแรกจะตรวจสอบว่าโปรแกรมได้รับอาร์กิวเมนต์ ($1) หรือไม่ ถ้าไม่เช่นนั้น โปรแกรมจะยุติการทำงานโดยแสดงข้อความแสดงข้อผิดพลาดเล็กน้อยแก่ผู้ใช้ ส่วนที่เหลือของสคริปต์ในตอนนี้สามารถอธิบายได้ด้วยตนเองอย่างชัดเจน

เบ็ดเตล็ด

การอ่านอินพุตของผู้ใช้ด้วยการอ่าน

ในบางกรณีอาจจำเป็นต้องขอให้ผู้ใช้ป้อนข้อมูลบางอย่าง มีหลายวิธีในการทำเช่นนี้ วิธีหนึ่งมีดังต่อไปนี้:

#!/bin/bash
echo กรุณากรอกชื่อของคุณ
อ่านชื่อ
สะท้อน "สวัสดี $NAME!"

หรือคุณสามารถรับหลายค่าพร้อมกันโดยใช้การอ่าน ตัวอย่างต่อไปนี้อธิบายสิ่งนี้:
#!/bin/bash
echo "กรุณากรอกชื่อและนามสกุลของคุณ"
อ่าน FN LN #FN - ชื่อ - ชื่อ; LN - นามสกุล - นามสกุล
สะท้อน "สวัสดี! $LN, $FN !"

การคำนวณทางคณิตศาสตร์

ที่บรรทัดคำสั่ง (หรือเชลล์) ให้ลองพิมพ์ข้อความต่อไปนี้:
เสียงก้อง;1;+;1
หากคุณคาดหวังที่จะเห็น "2" คุณจะต้องผิดหวัง คุณควรทำอย่างไรถ้าคุณต้องการ BASH เพื่อคำนวณตัวเลขของคุณ? วิธีแก้ไขคือ:
เสียงสะท้อน;$((1+1))
เป็นผลให้ข้อสรุปจะเป็น "ตรรกะ" มากขึ้น สัญกรณ์นี้ใช้เพื่อประเมินนิพจน์ทางคณิตศาสตร์ คุณสามารถทำได้เช่นนี้:
เสียงสะท้อน;$
หากคุณต้องการใช้เศษส่วนหรือคณิตศาสตร์ที่ซับซ้อนมากขึ้น คุณสามารถใช้ bc เพื่อประเมินนิพจน์ทางคณิตศาสตร์ได้
เมื่อผู้เขียนรัน "echo;$" ในเชลล์ มันจะส่งคืนค่า 0 เนื่องจากหาก bash ตอบสนอง จะใช้เฉพาะค่าจำนวนเต็มเท่านั้น หากคุณเรียกใช้ "echo;3/4|bc;-l" เชลล์จะส่งกลับค่าที่ถูกต้อง 0.75

ค้นหาทุบตี

จากข้อความจากไมค์ (ดูหัวข้อ "การรับทราบ"):

คุณมักจะใช้ #!/bin/bash .. คุณช่วยยกตัวอย่างวิธีค้นหาตำแหน่งของ bash ได้ไหม
ควรใช้ "locate bash" แต่การค้นหาไม่สามารถใช้ได้ในทุกเครื่อง
"find ./ -name bash" จากไดเรกทอรีรากมักจะใช้งานได้
คุณสามารถตรวจสอบสถานที่ต่อไปนี้:
ls -l /bin/bash
ls -l /sbin/bash
ls -l /usr/local/bin/bash
ls -l /usr/bin/bash
ls -l /usr/sbin/bash
ls -l /usr/local/sbin/bash
(ผู้เขียนไม่สามารถนึกถึงไดเร็กทอรีอื่นได้ทันที... เขาพบว่ามีทุบตีในสถานที่เหล่านี้ส่วนใหญ่ในระบบต่างๆ)

คุณยังสามารถลอง "ทุบตีอันไหน" ได้

รับค่าส่งคืนของโปรแกรม

ใน bash ค่าที่ส่งคืนของโปรแกรมจะถูกเก็บไว้ในตัวแปรพิเศษที่เรียกว่า $?

ตัวอย่างนี้แสดงให้เห็นถึงวิธีการสกัดกั้นค่าที่ส่งคืนของโปรแกรม ผู้เขียนสันนิษฐานว่าไม่มีไดเร็กทอรี dada (ไมค์แนะนำเช่นกัน)
#!/bin/bash
ซีดี /ดาด้า &> /dev/null
เสียงสะท้อน RV: $?
ซีดี $(pwd) &> /dev/null
เสียงสะท้อน RV: $?


สกัดกั้นเอาต์พุตคำสั่ง

สคริปต์ขนาดเล็กนี้นำเสนอตารางทั้งหมดจากฐานข้อมูลทั้งหมด (สมมติว่าคุณติดตั้ง MySQL) นอกจากนี้ คุณควรพิจารณาวิธีแปลงคำสั่ง "mysql" ให้ใช้ชื่อผู้ใช้และรหัสผ่านที่เหมาะสม
#!/bin/bash
DBS=`mysql -uroot -e"แสดงฐานข้อมูล"`
สำหรับ b ใน $DBS ;
ทำ
mysql -uroot -e"แสดงตารางจาก $b"
เสร็จแล้ว

ไฟล์ต้นฉบับหลายไฟล์

คุณสามารถเรียกใช้หลายไฟล์ได้โดยใช้คำสั่ง source

ทำ__
11. โต๊ะ
11.1 ตัวดำเนินการเปรียบเทียบสตริง
(1) s1 = s2
(2) s1 != s2
(3) ส1< s2
(4) s1 > s2
(5) -ไม่มี ส1
(6) -z s1
(1) s1 เกิดขึ้นพร้อมกับ s2
(2) s1 ไม่ตรงกับ s2
(3) s1 เรียงตามตัวอักษรนำหน้า s2 (ตามสถานที่ปัจจุบัน)
(4) s1 มาตามลำดับตัวอักษรหลังจาก s2 (ตามสถานที่ปัจจุบัน)
(5) s1 มีค่าไม่เป็นศูนย์ (ประกอบด้วยอักขระหนึ่งตัวขึ้นไป)
(6) s1 มีค่าเป็นศูนย์
11.2 ตัวอย่างการเปรียบเทียบสตริง

เปรียบเทียบสองสาย
#!/bin/bash
S1="สตริง"
S2="สตริง"
ถ้า [ $S1=$S2 ];
แล้ว
เสียงสะท้อน "S1("$S1") ไม่เท่ากับ S2("$S2")"
ฟิ
ถ้า [ $S1=$S1 ];
แล้ว
เสียงสะท้อน "S1("$S1") เท่ากับ S1("$S1")"
ฟิ
ณ จุดนี้ ผู้เขียนรู้สึกว่าจำเป็นต้องอ้างอิงคำพูดจากอีเมลที่ได้รับจาก Andreas Beck เกี่ยวกับการใช้ if [ $1 = $2 ]
นี่ไม่ใช่ความคิดที่ดี เนื่องจากหากเป็น $S1 หรือ $S2 บรรทัดว่างคุณจะได้รับข้อผิดพลาดทางไวยากรณ์ มันจะเป็นที่ยอมรับมากกว่าถ้าใช้หรือ x$1;=;x$2 "$1";=;"$2"
11.3 ตัวดำเนินการทางคณิตศาสตร์
+
-
*
% (ส่วนที่เหลือ)
11.4 ตัวดำเนินการเปรียบเทียบทางคณิตศาสตร์
-lt (<)
-gt (>)
-เลอ (<=)
-ge (>=)
-eq (==)
-เน่ (!=)
โปรแกรมเมอร์ภาษา C เพียงแค่ต้องเลือกตัวดำเนินการที่ตรงกับตัวดำเนินการที่เลือกในวงเล็บ

คำสั่งที่เป็นประโยชน์

ส่วนนี้เขียนใหม่โดย Kees (ดูส่วนการรับทราบ)

คำสั่งเหล่านี้บางคำสั่งมีภาษาคำสั่งที่ครบถ้วน อธิบายเฉพาะพื้นฐานของคำสั่งดังกล่าวเท่านั้นที่นี่ สำหรับรายละเอียดเพิ่มเติม ให้ตรวจสอบ man page ของแต่ละคำสั่งอย่างละเอียด
sed (โปรแกรมแก้ไขสตรีม)
Sed เป็นตัวแก้ไขแบบไม่โต้ตอบ แทนที่จะเปลี่ยนไฟล์โดยเลื่อนเคอร์เซอร์บนหน้าจอ คุณควรใช้สคริปต์คำแนะนำการแก้ไข sed พร้อมกับชื่อไฟล์ที่คุณกำลังแก้ไข คุณยังสามารถนึกถึง sed เป็นตัวกรองได้ ดูตัวอย่างบางส่วน:
$sed "s/to_be_replaced/replaced/g" /tmp/dummy
Sed แทนที่สตริง "to_be_replaced" ด้วยสตริง "แทนที่" โดยการอ่านไฟล์ /tmp/dummy ผลลัพธ์จะถูกส่งไปยังเอาต์พุตมาตรฐาน (โดยปกติคือคอนโซล) แต่คุณสามารถเพิ่ม ">;capture" ลงในบรรทัดด้านบนเพื่อให้ sed ส่งเอาต์พุตไปยังไฟล์ "capture"
$sed 12, 18d /tmp/dummy
Sed แสดงทุกบรรทัด ยกเว้นบรรทัดที่ 12 ถึง 18 ไฟล์ต้นฉบับจะไม่ถูกเปลี่ยนแปลงโดยคำสั่งนี้
awk (การจัดการไฟล์ข้อมูล การดึงข้อความ และการประมวลผล)
มีการใช้งานภาษาโปรแกรม AWK เป็นจำนวนมาก (ล่ามที่พบบ่อยที่สุดคือ gawk จากโปรเจ็กต์ GNU และ mawk "new awk") หลักการค่อนข้างง่าย: AWK กำลังค้นหารูปแบบ; สำหรับแต่ละเทมเพลตที่ตรงกัน จะมีการดำเนินการบางอย่าง
ผู้เขียนได้สร้างไฟล์จำลองที่มี บรรทัดต่อไปนี้:
"ทดสอบ123
ทดสอบ
ทีนี้”

$awk "/test/ (พิมพ์)" /tmp/dummy
ทดสอบ123
ทดสอบ
รูปแบบที่ AWK ค้นหาคือ "ทดสอบ" และการดำเนินการที่ AWK เกิดขึ้นเมื่อพบบรรทัดใน /tmp/dummy โดยมีสตริงย่อย "test" คือ "print"
$awk "/test/ (i=i+1) END (พิมพ์ i)" /tmp/dummy
หากคุณกำลังค้นหาหลายรูปแบบ ให้แทนที่ข้อความระหว่างเครื่องหมายคำพูดด้วย "-f;file.awk" ในกรณีนี้ คุณสามารถเขียนเทมเพลตและการดำเนินการทั้งหมดลงในไฟล์ "file.awk" ได้
grep (พิมพ์บรรทัดที่ตรงกับรูปแบบการค้นหา)
เราได้ดูคำสั่ง grep หลายคำสั่งในบทที่แล้วซึ่งแสดงบรรทัดที่ตรงกับรูปแบบ อย่างไรก็ตาม grep สามารถทำได้มากกว่านั้นมาก
$grep "มองหาสิ่งนี้" /var/log/messages -c
พบสตริง "look for this" 12 ครั้งใน /var/log/messages
wc (นับบรรทัด คำ และไบต์)
ในตัวอย่างต่อไปนี้ คุณจะสังเกตเห็นว่าผลลัพธ์ไม่ใช่สิ่งที่เราคาดหวัง ในกรณีนี้ ไฟล์จำลองจะมีข้อความต่อไปนี้:
"แนะนำทุบตี
วิธีทดสอบไฟล์"
$wc --words --lines --bytes /tmp/dummy
2 5 34 /tmp/หุ่นจำลอง
wc ไม่สนใจลำดับของพารามิเตอร์ เขามักจะพาพวกเขาออกไป ขั้นตอนมาตรฐาน: <число;строк><число;слов><число;байтов><имя;файла>.
sort (เรียงลำดับบรรทัดของไฟล์ข้อความ)

ในกรณีนี้ ไฟล์จำลองจะมีข้อความต่อไปนี้:
"ข

ก"
$sort /tmp/dummy
ผลลัพธ์มีลักษณะดังนี้:



คำสั่งไม่ควรง่ายขนาดนี้ :-)
bc (ภาษาโปรแกรมคอมพิวเตอร์)
bc ทำการคำนวณจากบรรทัดคำสั่ง (อินพุตจากไฟล์ แต่ไม่ใช่ผ่านการเปลี่ยนเส้นทางหรือไปป์ไลน์) รวมถึงจากอินเทอร์เฟซผู้ใช้ ตัวอย่างต่อไปนี้แสดงคำสั่งบางคำสั่ง โปรดทราบว่าผู้เขียนใช้ bc พร้อมกับตัวเลือก -q เพื่อระงับข้อความแจ้ง
$บีซี -คิว
1 == 5
0
0.05 == 0.05
1
5 != 5
0
2 ^ 8
256
ตารางวา(9)
3
ในขณะที่ ( ผม != 9) (
ฉัน = ฉัน + 1;
พิมพ์ฉัน
}
123456789
ล้มเลิก
tput (เริ่มต้นเทอร์มินัลหรือสอบถามฐานข้อมูล terminfo)
ภาพประกอบเล็กๆ น้อยๆ ของความสามารถของ tput:

$tput ถ้วย 10 4
พรอมต์คำสั่งจะปรากฏที่พิกัด (y10,x4)
$tput รีเซ็ต
หน้าจอหายไปและข้อความแจ้งปรากฏขึ้นที่ (y1,x1) โปรดทราบว่า (y0,x0) คือมุมซ้ายบน
$tputcols
80 แสดงจำนวนอักขระที่เป็นไปได้ในทิศทาง x
ขอแนะนำอย่างยิ่งให้ทำความคุ้นเคยกับโปรแกรมเหล่านี้ (อย่างน้อย) มีโปรแกรมขนาดเล็กจำนวนมากที่เปิดโอกาสให้คุณทำเวทย์มนตร์จริงบนบรรทัดคำสั่ง
[ตัวอย่างบางส่วนนำมาจากหน้าคู่มือหรือคำถามที่พบบ่อย]

สคริปต์เพิ่มเติม

ใช้คำสั่งกับไฟล์ทั้งหมดในไดเร็กทอรี

ตัวอย่าง: สคริปต์สำรองข้อมูลที่ง่ายมาก (มีประสิทธิภาพมากกว่า)

#!/bin/bash
SRCD="/home/" #SRCD - ไดเรกทอรี SouRCe - ไดเรกทอรีต้นทาง
TGTD="/var/backups/" #TGTD - ไดเรกทอรี TarGeT - ไดเรกทอรีสุดท้าย
OF=home-$(date +%Y%m%d).tgz #OF - ไฟล์เอาท์พุต - ไฟล์เอาท์พุต
tar -cZf $TGTD$ของ $SRCD

โปรแกรมเปลี่ยนชื่อไฟล์

#!/bin/sh
# renna: เปลี่ยนชื่อหลายไฟล์โดยใช้กฎพิเศษ
# ผู้แต่ง - เฟลิกซ์ ฮัดสัน ม.ค. - 2000

#ก่อนอื่นมาดู "โหมด" ต่างๆ ของโปรแกรมนี้กันก่อน
#หากอาร์กิวเมนต์แรก ($1) เหมาะสม เราจะดำเนินการส่วนนี้
#โปรแกรมแล้วออก.

# ตรวจสอบความเป็นไปได้ในการเพิ่มคำนำหน้า
ถ้า [ $1 = p ]; แล้ว

#เอาล่ะมาต่อจาก ตัวแปรโหมด($1) และคำนำหน้า ($2)
คำนำหน้า=$2 ; กะ ; กะ

# ต้องตรวจสอบว่าระบุอย่างน้อยหนึ่งไฟล์หรือไม่
# มิฉะนั้น เป็นการดีกว่าที่จะไม่ทำอะไรเลยนอกจากเปลี่ยนชื่อที่ไม่มีอยู่จริง
#ไฟล์!!

ถ้า [$1 = ]; แล้ว

ทางออก 0
ฟิ

# สิ่งนี้สำหรับลูปจะประมวลผลไฟล์ทั้งหมดที่เราระบุไว้
# โปรแกรม.
# ทำการเปลี่ยนชื่อหนึ่งครั้งต่อไฟล์
สำหรับไฟล์ใน $*
ทำ
mv $(ไฟล์) $คำนำหน้า$ไฟล์
เสร็จแล้ว

#หลังจากนี้ออกจากโปรแกรมแล้ว
ทางออก 0
ฟิ

#ตรวจสอบเงื่อนไขการเติมคำต่อท้าย
# มิฉะนั้น, ส่วนนี้แทบจะเหมือนกับส่วนก่อนหน้า
# โปรดดูความคิดเห็นที่มีอยู่ในนั้น
ถ้า [ $1 = วิ ]; แล้ว
ต่อท้าย=$2 ; กะ ; กะ
ถ้า [$1 = ]; แล้ว
echo "ไม่ได้ระบุไฟล์"
ทางออก 0
ฟิ
สำหรับไฟล์ใน $*
ทำ
mv $(ไฟล์) $file$suffix
เสร็จแล้ว
ทางออก 0
ฟิ

# ตรวจสอบสภาพการเปลี่ยนชื่อพร้อมการเปลี่ยน
ถ้า [ $1 = r ]; แล้ว
กะ
# ด้วยเหตุผลด้านความปลอดภัย ผู้เขียนได้รวมส่วนนี้ไว้เพื่อไม่ให้ไฟล์ใดๆ เสียหายหากผู้ใช้
#ไม่ได้กำหนดว่าต้องทำอะไร:
ถ้า [ $# -lt 3 ] ; แล้ว
echo "ข้อผิดพลาด; อินพุตที่ถูกต้อง: ไฟล์ renna r [นิพจน์] [แทนที่] ... "
ทางออก 0
ฟิ

#เรามาดูข้อมูลอื่นๆกันดีกว่า
เก่า=$1 ; ใหม่=$2 ; กะ ; กะ

# สิ่งนี้ for loop ตามลำดับจะผ่านไฟล์ทั้งหมดที่เรา
#กำหนดให้กับโปรแกรม
# จะเปลี่ยนชื่อหนึ่งครั้งต่อไฟล์โดยใช้โปรแกรม "sed"
# นี้ โปรแกรมง่ายๆจากบรรทัดคำสั่งซึ่งแยกวิเคราะห์มาตรฐาน
# อินพุตและแทนที่นิพจน์ทั่วไปด้วยสตริงที่กำหนด
# ที่นี่เราให้ชื่อไฟล์ sed (เป็นอินพุตมาตรฐาน) และแทนที่
#ข้อความที่ต้องการ
สำหรับไฟล์ใน $*
ทำ
ใหม่=`echo $(ไฟล์) | sed s/$(เก่า)/$(ใหม่)/g`
mv $(ไฟล์) $new
เสร็จแล้ว
ทางออก 0
ฟิ
#ถ้าเราไปถึงเส้นนี้แสดงว่าได้รับโปรแกรมแล้ว
# พารามิเตอร์ไม่ถูกต้อง ในเรื่องนี้ควรอธิบายให้ผู้ใช้ทราบถึงวิธีการ
# ใช้
สะท้อน "ใช้:"
echo "ไฟล์ renna p [คำนำหน้า] .."
echo "ไฟล์ [ส่วนต่อท้าย] renna .."
echo "ไฟล์ renna r [การแสดงออก] [การแทนที่] .."
ทางออก 0
#เสร็จแล้ว!

โปรแกรมเปลี่ยนชื่อไฟล์ (แบบง่าย)
#!/bin/bash
#renames.sh
#โปรแกรมเปลี่ยนชื่อง่ายๆ

เกณฑ์=$1
รี_แมทช์=$2
แทนที่=$3

สำหรับฉันใน $(ls *$criteria*);
ทำ
src=$i
tgt=$(echo $i | sed -e "s/$re_match/$replace/")
mv $src $tgt
เสร็จแล้ว

หากสิ่งที่เกิดขึ้นแตกต่างจากที่คุณคาดหวัง (แก้ไขจุดบกพร่อง)

ฉันจะโทรหา BASH ได้อย่างไร?

เป็นการดีที่จะเพิ่มในบรรทัดแรก

#!/bin/bash -x
สิ่งนี้จะสร้างข้อมูลผลลัพธ์ที่น่าสนใจ

เกี่ยวกับเอกสาร

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

แผ่นโกงนี้ครอบคลุม หัวข้อต่อไปนี้: ข้อมูลเบื้องต้นเกี่ยวกับเชลล์, การนำทาง, คำสั่งพื้นฐาน, ตัวแปรสภาพแวดล้อม, ตัวเชื่อมต่อ, ไปป์ไลน์, การเปลี่ยนเส้นทาง I/O, สิทธิ์ และชุดคีย์

Bash Shell: บทนำ

เชลล์หรือเชลล์คือโปรแกรมในกรณีของเราที่เรียกว่า "bash" ซึ่งย่อมาจาก Bourne Again Shell เชลล์ยอมรับคำสั่งของคุณและส่งต่อ ระบบปฏิบัติการ- ในการโต้ตอบกับระบบ เทอร์มินัลจะถูกใช้ เช่น gnome-terminal, eterm, nxterm เป็นต้น

การนำทาง

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

นโยบายความเป็นส่วนตัว

คำสั่ง pwd ย่อมาจาก พิมพ์ไดเร็กทอรีการทำงาน, แสดงผล สถานที่ปัจจุบันในโครงสร้างไดเร็กทอรี

ซีดี

คำสั่ง cd อนุญาตให้คุณเปลี่ยนเป็นไดเร็กทอรีใหม่

mkdir

คำสั่ง mkdir สร้างไดเร็กทอรีใหม่ในไดเร็กทอรีปัจจุบัน

คำสั่งพื้นฐาน

ผู้ชาย

คำสั่ง man แสดงคู่มือคำสั่ง ตัวอย่างเช่น คำสั่งต่อไปนี้จะแสดงข้อมูลทั้งหมดเกี่ยวกับ คำสั่งแมว:

$ ผู้ชาย แมว

แมว

คำสั่ง cat อ่านไฟล์ที่ส่งเป็นอาร์กิวเมนต์และพิมพ์เนื้อหา ช่องมาตรฐานเอาท์พุท การส่งผ่านหลายไฟล์เป็นอาร์กิวเมนต์จะพิมพ์เนื้อหาที่ต่อกันของไฟล์ทั้งหมด

เสียงสะท้อน

คำสั่ง echo พิมพ์อาร์กิวเมนต์ไปยังเอาต์พุตมาตรฐาน

$ echo สวัสดีชาวโลก สวัสดีชาวโลก

การเรียก echo โดยไม่มีข้อโต้แย้งจะพิมพ์สตริงว่าง

ศีรษะ

คำสั่ง head อ่าน 10 บรรทัดแรกของข้อความที่ส่งผ่านและส่งออกไปยังไพพ์มาตรฐาน จำนวนบรรทัดที่แสดงสามารถเปลี่ยนแปลงได้:

$หัว -50 test.txt

หาง

คำสั่ง tail ทำงานคล้ายกับคำสั่ง head แต่อ่านบรรทัดจากส่วนท้าย:

$ หาง -50 test.txt

คุณยังสามารถดูบรรทัดที่ถูกเพิ่มลงในไฟล์แบบเรียลไทม์โดยใช้แฟล็ก -f:

$ หาง -f test.txt

น้อย

คำสั่ง less ช่วยให้คุณสามารถนำทางผ่านไฟล์หรือข้อความที่ถ่ายโอนได้ทั้งสองทิศทาง

$ test.txt น้อยกว่า $ ps aux | น้อย

เรียนรู้เพิ่มเติมเกี่ยวกับวัตถุประสงค์ของสัญลักษณ์ | จะกล่าวถึงด้านล่างในส่วนประวัติของคำสั่ง

แป้นพิมพ์ลัดทั่วไปคำอธิบาย
ย้ายไปที่ส่วนท้ายของไฟล์
ย้ายไปที่จุดเริ่มต้นของไฟล์
:50 ย้ายไปที่บรรทัดที่ 50 ของไฟล์
ถามออกให้น้อยลง
/คำที่ต้องการค้นหาค้นหาสตริงที่ตรงกับ 'คำค้นหา' ด้านล่าง เส้นปัจจุบัน
/
?คำที่ต้องการค้นหาค้นหาบรรทัดที่ตรงกับ 'คำค้นหา' เหนือบรรทัดปัจจุบัน
? ย้ายไปยังผลการค้นหาที่ตรงกันถัดไป
ขึ้นเลื่อนขึ้นไปหนึ่งบรรทัด
ลงเลื่อนลงหนึ่งบรรทัด
เพจอัพเลื่อนขึ้นหนึ่งหน้า
เลื่อนหน้าลงเลื่อนลงหนึ่งหน้า

จริง

คำสั่ง true จะคืนค่าศูนย์เป็นสถานะเอาต์พุตเสมอเพื่อบ่งชี้ความสำเร็จ

เท็จ

คำสั่ง false จะส่งคืนสถานะเอาต์พุตที่ไม่ใช่ศูนย์เสมอเพื่อบ่งชี้ถึงความล้มเหลว

$?

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

$จริง$เอคโค$? 0 $ เท็จ $ echo $? 1

เกรป

คำสั่ง grep ค้นหาสตริงที่ส่งผ่านเข้ามา ไฟล์ที่ระบุ:

$ cat users.txt ผู้ใช้: รหัสผ่านนักเรียน: 123 ผู้ใช้: รหัสผ่านครู: 321 $ grep "นักเรียน ` file1.txt ผู้ใช้: รหัสผ่านนักเรียน: 123

grep ยังสามารถรับหลายไฟล์และ การแสดงออกปกติเพื่อชี้แจงรูปแบบข้อความ

ประวัติศาสตร์

คำสั่ง history จะแสดงประวัติบรรทัดคำสั่ง โดยปกติแล้วจะใช้ร่วมกับคำสั่ง grep เพื่อค้นหาคำสั่งเฉพาะ ตัวอย่างเช่น โค้ดต่อไปนี้จะค้นหาคำสั่งทั้งหมดที่มีสตริง g++ :

$ประวัติศาสตร์ | grep g++ 155 g++ file1.txt 159 g++ file2.txt

สัญลักษณ์ | ถูกใช้ที่นี่ด้วย - นี่คือสิ่งที่เรียกว่าสายพานลำเลียง (ท่อ) ด้วยเหตุนี้คุณจึงสามารถเปลี่ยนเส้นทางเอาต์พุตของคำสั่งหนึ่งไปยังอินพุตของอีกคำสั่งหนึ่งได้ - ดังนั้นในตัวอย่างข้างต้น เรื่องราวทั้งหมดซึ่งใน โหมดปกติเอาต์พุตโดยคำสั่ง history ไปยังเอาต์พุตเทอร์มินัลโดยตรงจะถูกเปลี่ยนเส้นทางไปยัง grep เป็นอินพุต เราจะไม่เห็นผลลัพธ์ของคำสั่ง history แต่เราจะเห็นผลของคำสั่ง grep

สิ่งนี้อาจเป็นเรื่องยากที่จะเข้าใจโดยไม่ต้องฝึกฝน ดังนั้นให้ทดลองด้วยตัวเองด้วยคำสั่ง ls , history , ps (อธิบายไว้ด้านล่าง) เพื่อเปลี่ยนเส้นทางเอาต์พุตไปที่ grep , sed หรือน้อยกว่า เป็นต้น

ส่งออก

คำสั่งส่งออกตั้งค่าตัวแปรสภาพแวดล้อมเพื่อส่งผ่านไปยังกระบวนการลูก ตัวอย่างเช่น นี่คือวิธีที่คุณสามารถส่งตัวแปรชื่อด้วยค่าของนักเรียน:

$ ส่งออกชื่อ = นักเรียน

ปล

คำสั่ง PS แสดงข้อมูลเกี่ยวกับ กระบวนการทำงานอยู่.

$ ps PID TTY TIME CMD 35346 pts/2 00:00:00 ทุบตี

สี่องค์ประกอบจะถูกส่งออก:

  • รหัสกระบวนการ (PID)
  • ประเภทเทอร์มินัล (TTY)
  • เวลาดำเนินการของกระบวนการ (TIME)
  • ชื่อของคำสั่งที่เริ่มกระบวนการ (CMD)

โอเค

คำสั่ง awk ค้นหาและแทนที่ข้อความในไฟล์โดยใช้รูปแบบที่กำหนด: awk "รูปแบบ (การกระทำ)" test.txt

ตกลง

คำสั่ง wget ดาวน์โหลดไฟล์จากอินเทอร์เน็ตและวางไว้ในนั้น ไดเรกทอรีปัจจุบัน.

$ wget https://github.com/mikeizbicki/ucr-cs100

nc

ปิง

การทดสอบคำสั่ง ping การเชื่อมต่อเครือข่าย.

$ ping google.com PING google.com (74.125.224.34) ข้อมูล 56 (84) ไบต์ 64 ไบต์จาก lax17s01-in-f2.1e100.net (74.125.224.34): icmp_req=1 ttl=57 time=7.82 ms --- สถิติการ ping ของ google.com --- ส่ง 1 แพ็กเก็ต, 1 ได้รับ, สูญเสียแพ็กเก็ต 0% เวลา 8ms rtt ขั้นต่ำ/เฉลี่ย/สูงสุด/mdev = 7.794/8.422/10.792/0.699 ms

สถิติในตอนท้ายแสดงจำนวนการเชื่อมต่อที่เกิดขึ้นก่อนที่คำสั่งจะเสร็จสิ้น และเวลาที่ใช้ในการดำเนินการให้เสร็จสิ้น

คอมไพล์

ตัวแปรสภาพแวดล้อม

ตัวแปรสภาพแวดล้อมเป็นตัวแปรที่มีชื่อซึ่งมีค่าที่ใช้โดยแอปพลิเคชันหนึ่งรายการขึ้นไป

ตัวแปร PATH ประกอบด้วยรายการไดเร็กทอรีที่ระบบค้นหาไฟล์ปฏิบัติการ

ตัวแปร HOME มีเส้นทางไปยัง โฮมไดเร็กทอรีผู้ใช้ปัจจุบัน.

ขั้วต่อ

ตัวเชื่อมต่อช่วยให้คุณสามารถรันหลายคำสั่งพร้อมกันได้

$ true && echo สวัสดี สวัสดี $ false || echo สวัสดี สวัสดี $ echo สวัสดี ; ls สวัสดี test.txt file1.txt file2.txt

สายพานลำเลียง

สายพานลำเลียงหรือท่อช่วยให้คุณสามารถเชื่อมต่อช่องอินพุตและเอาต์พุตของทีมต่างๆ ในตัวอย่างต่อไปนี้ ผลลัพธ์ของคำสั่ง ls จะถูกส่งไปที่ head และจะพิมพ์เฉพาะ 10 องค์ประกอบแรกเท่านั้น

$ ls -l | ศีรษะ

การเปลี่ยนเส้นทาง I/O

การเปลี่ยนเส้นทางเอาต์พุต

สำหรับ การเปลี่ยนเส้นทางมาตรฐานใช้สัญลักษณ์เอาท์พุต > และ >>

ตัวอย่างเช่น โค้ดนี้จะไปป์ ls เอาต์พุตไปที่ไฟล์ แทนที่จะไปที่หน้าจอ:

$ ls > files.txt $ cat files.txt file1.cpp ตัวอย่าง.txt

หากไม่มีไฟล์อยู่ ไฟล์จะถูกสร้างขึ้น และหากมีอยู่ ไฟล์นั้นจะถูกเขียนทับ เพื่อหลีกเลี่ยงการเขียนทับ คุณควรใช้คำสั่ง >> ซึ่งจะผนวกข้อมูลต่อท้ายไฟล์

การเปลี่ยนเส้นทางอินพุต

สำหรับการเปลี่ยนทิศทางเอาต์พุตมาตรฐาน ให้ใช้สัญลักษณ์< . В следующем примере sort берет входные данные из файла, а не с клавиатуры:

$ cat files.txt c b $ เรียงลำดับ< files.txt b c

คำสั่ง sort จะพิมพ์เนื้อหาของไฟล์ไปที่หน้าจอ เนื่องจากเราไม่ได้เปลี่ยนเส้นทางเอาต์พุต ซึ่งสามารถทำได้เช่นนี้:

$เรียงลำดับ< files.txt >files_sorted.txt

การเปลี่ยนเส้นทางขั้นสูง

การเพิ่ม & to > ผลลัพธ์ในการเปลี่ยนเส้นทางเช่น กระแสมาตรฐานเอาต์พุตและการไหลของข้อผิดพลาด ตัวอย่างเช่น ไฟล์ test.cpp จะส่งออกบรรทัด stdout ไปที่ cout และบรรทัด stderr ไปที่ cerr

$ g++ test.cpp $ ./a.out >& test.txt $ cat test.txt stdout stderr

หากคุณต้องการส่งออกเฉพาะ ตัวอธิบายไฟล์คุณสามารถกำหนดหมายเลขให้กับ > ได้

ชื่อคำอธิบายคำอธิบาย
มาตรฐาน0 อินพุตมาตรฐาน
มาตรฐาน1 เอาต์พุตมาตรฐาน
stderr2 เอาต์พุตข้อผิดพลาดมาตรฐาน

ตัวอย่างเช่น หากต้องการเปลี่ยนเส้นทาง stderr ไปที่ test.txt คุณจะต้องดำเนินการดังต่อไปนี้:

$ g++ test.cpp $ ./a.out 2> test.txt stdout $ cat test.txt stderr

สิทธิ์การเข้าถึง

คำสั่ง ls -l แสดงข้อมูลจำนวนมากเกี่ยวกับการอนุญาตของแต่ละไฟล์:

โครโมด

คำสั่ง chmod เปลี่ยนการอนุญาตของไฟล์ ต่อไปนี้คือชุดค่าสถานะทั่วไปสำหรับการเปลี่ยนสิทธิ์ของผู้ใช้บางราย:

คุณสามารถเรียก chmod พร้อมคำอธิบายว่าต้องทำอย่างไรกับไฟล์ใดไฟล์หนึ่ง สัญลักษณ์ - หมายถึง การลบสิทธิ์ สัญลักษณ์ + หมายถึง การบวก ตัวอย่างต่อไปนี้จะทำให้เจ้าของและกลุ่มสามารถอ่านและเขียนไฟล์ได้:

$ chmod ug+rw test.txt $ ls -l test.txt -rw-rw ---- กลุ่มผู้ใช้ 1 กลุ่ม 1097374 26 มกราคม 2:48 test.txt

นอกจากนี้ยังสามารถใช้ chmod ได้ด้วย เลขฐานแปดโดยที่ 1 คือ การมีอยู่ของสิทธิ และ 0 คือ การไม่มี:

Rwx = 111 = 7 rw- = 110 = 6 r-x = 101 = 5 r-- = 100 = 4

คำสั่งถัดไปจะทำงานเหมือนกับคำสั่งก่อนหน้า