ฉันต้องการเปลี่ยนจาก bash เป็น zsh แต่กังวลเกี่ยวกับความเข้ากันได้ของสคริปต์ทุบตี
bash สคริปต์ / ฟังก์ชั่นทั้งหมดเข้ากันได้กับ zsh หรือไม่ ดังนั้นถ้าเป็นจริงก็คือ zsh เพียงการเพิ่มประสิทธิภาพในการทุบตี?
ฉันต้องการเปลี่ยนจาก bash เป็น zsh แต่กังวลเกี่ยวกับความเข้ากันได้ของสคริปต์ทุบตี
bash สคริปต์ / ฟังก์ชั่นทั้งหมดเข้ากันได้กับ zsh หรือไม่ ดังนั้นถ้าเป็นจริงก็คือ zsh เพียงการเพิ่มประสิทธิภาพในการทุบตี?
คำตอบ:
หากสคริปต์ของคุณเริ่มต้นด้วยบรรทัดสคริปต์#!/bin/bash
เหล่านั้นจะยังคงทำงานโดยใช้ bash แม้ว่าเชลล์เริ่มต้นของคุณคือ zsh
ฉันพบไวยากรณ์ของ zsh จริงๆแล้วใกล้กับ bash หนึ่งอันและฉันไม่สนใจถ้ามีความเข้ากันไม่ได้จริง ๆ ฉันเปลี่ยน 6 ปีที่ผ่านมาจาก bash เป็น zsh อย่างราบรื่น
.zshrc
:)
#!/bin/bash
จะถูกละเว้นหากเรียกใช้ไฟล์สคริปต์เป็นsource ./script.sh
อย่างไร
#!/usr/bin/env bash
แทนโดยเฉพาะอย่างยิ่งใน macOS ซึ่ง bash เริ่มต้นล้าสมัยอย่างรุนแรงและมีการติดตั้งเวอร์ชันใหม่ในพา ธ ที่แตกต่างกัน
Zsh สามารถรันสคริปต์ Bourne, POSIX หรือ ksh88 ส่วนใหญ่หากคุณวางไว้ในโหมดการจำลองที่ถูกต้อง ( emulate sh
หรือemulate ksh
) ไม่รองรับคุณสมบัติทั้งหมดของ bash หรือ ksh93 Zsh มีคุณสมบัติส่วนใหญ่ของการทุบตี แต่ในหลายกรณีด้วยไวยากรณ์ที่แตกต่างกัน
เชลล์ที่คุณใช้แบบโต้ตอบนั้นไม่เกี่ยวข้องกับสคริปต์ใด ๆ ที่คุณมี เปลือกที่ทำงานสคริปต์เป็นหนึ่งที่ระบุไว้ในบรรทัดแรกที่shebangบรรทัด ตัวอย่างเช่นหากสคริปต์เริ่มต้นด้วยสคริปต์#!/bin/bash
จะถูกดำเนินการโดย bash
หากคุณได้ปรับแต่งทุบตีคุณจะไม่สามารถเพียงแค่เปลี่ยนชื่อของคุณจะ.bashrc
.zshrc
บางสิ่งสามารถใช้ร่วมกันได้เช่นนามแฝงและฟังก์ชั่นตราบใดที่คุณติดอยู่ที่จุดตัดระหว่างเปลือกหอยทั้งสอง (จุดตัดใกล้กับ ksh88 และpdksh ) สิ่งอื่น ๆ เช่นการตั้งค่าพรอมต์ฟังก์ชั่นเสร็จและตัวเลือกส่วนใหญ่จะต้องเขียนใหม่อย่างสมบูรณ์
หากคุณกำลังเขียนข้อมูลโค้ดสำหรับคนที่จะมาจากพวกเขา.bashrc
หรือ.zshrc
และคุณไม่ต้องการที่จะรักษาทั้งสองรุ่นติดชุดย่อยทั่วไปของการทุบตีและ zsh คุณสมบัติซึ่งรวมถึงส่วนใหญ่ของทุบตีคุณสมบัติการเขียนโปรแกรม ใส่โค้ดทั้งหมดของคุณลงในฟังก์ชันและวางบรรทัดต่อไปนี้ไว้ที่ด้านบนของแต่ละฟังก์ชัน:
if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi
คุณสามารถใช้emulate sh
แทนการที่จะได้ใกล้ชิดกับไวยากรณ์การดวลจุดโทษธรรมดาซึ่งเป็นสิ่งที่คุณต้องการสำหรับemulate ksh
.profile
หากฟังก์ชั่นเรียกใช้ฟังก์ชันอื่นฟังก์ชั่นอื่นจะสืบทอดการตั้งค่าเลียนแบบดังนั้นคุณไม่จำเป็นต้องใส่บรรทัดนี้ในฟังก์ชั่นภายในเฉพาะในฟังก์ชั่นที่เรียกโดยผู้ใช้ปลายทาง
./my_script.sh
คุณเรียกใช้สคริปต์ของคุณเป็น source my_script.sh
และ. my_script.sh
จะเรียกใช้มันเป็นเหมือนเชลล์ปัจจุบันโดยไม่สนใจ shebang ใด ๆ
หาก Shebang เป็น#!/bin/bash
และคุณเริ่มสคริปต์เป็น./script
สคริปต์จะถูกดำเนินการโดยทุบตี ไม่มีปัญหาที่นี่อย่างแน่นอน
อย่างไรก็ตามหากคุณดำเนินการzsh ./script
หรือส่ง. ./script
ไปยังอินสแตนซ์ที่กำลังทำงานอยู่ zsh เป็นเรื่องปกติที่ไวยากรณ์ของ bash และ zsh จะไม่ตรงกัน
ตัวอย่างเช่น zsh ไม่ได้แยกการขยายพารามิเตอร์โดยค่าเริ่มต้น bash มีวิธีใช้ในตัวไม่มีread -p prompt
zsh (ไวยากรณ์แตกต่างกันมากในการอ่าน cmd \? , arrays start on 1 (not 0) in zsh,
รับคำสั่งพรอมต์only search for external commands in zsh, or there is no (simple) equivalent to
$ {foo ^} `(ตัวอักษรตัวแรกเท่านั้น) ใน zsh หมู่คนอื่น ๆ . นี้เป็นรายการยาวของ (ส่วนใหญ่) ความเหมือนและความแตกต่างบางอย่าง
ในบางกรณี zsh อาจถูกบอกให้เลียนแบบเชลล์อื่น ในบางกรณีไม่มีไวยากรณ์ทั่วไปที่พกพาได้สำหรับเชลล์ทั้งสองที่เป็นไปได้ (โดยไม่ต้องใช้นามแฝงหรือฟังก์ชันเพื่อจำลองโซลูชันพกพา)
อย่างไรก็ตาม zsh มีส่วนขยายจำนวนมาก (มาก) ที่ทำให้การทำงานแบบโต้ตอบได้ง่ายขึ้น นั่นคือในเวลาเดียวกันเป็นเหตุผลที่ดีในการเปลี่ยนและปัญหา:
ls *(.)
ไลค์: ลิสต์ไฟล์เท่านั้น: (ซึ่งยากสำหรับเชลล์อื่น) แม้ว่าเมื่อมองลึกพอที่จะกลายเป็นคำตอบที่ยังมีความซับซ้อนใน zsh (print -rl -- *(/)
)Con zsh:
ในที่สุดมันก็เป็นทางเลือกของคุณและฉันก็ชอบตัวเลือกที่มากกว่าเสมอ