POSIX ต้อง printfของ%-20sการนับผู้ที่ 20 ในแง่ของไบต์ไม่ได้ตัวละครแม้ว่าที่ทำให้ความรู้สึกเล็ก ๆ น้อย ๆ เป็นprintfคือการพิมพ์ข้อความในรูปแบบ (ดูการอภิปรายที่ออสตินกลุ่ม (POSIX) และbashรายการทางไปรษณีย์)
printfbuiltin ของbashและส่วนใหญ่เปลือกหอย POSIX อื่น ๆ ที่ให้เกียรติ
zshไม่สนใจข้อกำหนดโง่ ๆ (แม้จะเป็นshอีมูเลชัน) ดังนั้นprintfทำงานได้ตามที่คุณคาดหวัง เหมือนกันสำหรับบิวด์อินprintfของfish(ไม่ใช่เชลล์เหมือน POSIX)
üตัวอักษร (U + 00FC) เมื่อการเข้ารหัสใน UTF-8 ทำสองไบต์ (0xc3 และ 0xbc) ซึ่งอธิบายถึงความแตกต่าง
$ printf %s 'Früchte und Gemüse' | wc -mcL
18 20 18
สตริงนั้นทำจาก 18 อักขระกว้าง 18 คอลัมน์ ( -Lเป็นwcส่วนขยายของGNU เพื่อรายงานความกว้างในการแสดงผลของบรรทัดที่กว้างที่สุดในอินพุต) แต่ถูกเข้ารหัสบน 20 ไบต์
ในzshหรือfishข้อความจะถูกจัดตำแหน่งอย่างถูกต้อง
ตอนนี้ยังมีอักขระที่มีความกว้าง 0 (เช่นการรวมอักขระเช่น U + 0308, diaresis รวม) หรือมีความกว้างสองเท่าเช่นในสคริปต์ Asiatic จำนวนมาก (ไม่พูดถึงอักขระควบคุมเช่น Tab) และแม้zshจะไม่จัดตำแหน่ง เหล่านั้นอย่างถูกต้อง
ตัวอย่างในzsh:
$ printf '%3s|\n' u ü $'u\u308' $'\u1100'
u|
ü|
ü|
ᄀ|
ในbash:
$ printf '%3s|\n' u ü $'u\u308' $'\u1100'
u|
ü|
ü|
ᄀ|
ksh93มี%Lsข้อกำหนดรูปแบบเพื่อนับความกว้างในแง่ของความกว้างของจอแสดงผล
$ printf '%3Ls|\n' u ü $'u\u308' $'\u1100'
u|
ü|
ü|
ᄀ|
ยังไม่สามารถใช้งานได้หากข้อความมีอักขระควบคุมเช่น TAB (จะเป็นไปได้อย่างไรprintfจะต้องทราบว่าแท็บหยุดห่างกันมากแค่ไหนในอุปกรณ์แสดงผลและตำแหน่งที่เริ่มพิมพ์) มันไม่ทำงานโดยอุบัติเหตุกับตัวละคร Backspace (เช่นเดียวกับในroffการส่งออกที่X(ตัวหนาX) เขียนเป็นX\bX) แต่เป็นพิจารณาตัวควบคุมทั้งหมดที่มีความกว้างของksh93-1
เช่นเดียวกับตัวเลือกอื่น ๆ คุณสามารถลอง:
printf '%s\t|\n' u ü $'u\u308' $'\u1100' | expand -t3
ที่ทำงานกับexpandการใช้งานบางอย่าง(ไม่ใช่ของ GNU)
บนระบบ GNU คุณสามารถใช้ GNU awkที่มีการprintfนับเป็นตัวอักษร (ไม่ใช่ไบต์ไม่ใช่ความกว้างของหน้าจอดังนั้นจึงยังไม่ตกลงสำหรับอักขระความกว้าง 0 หรือ 2 ความกว้าง แต่ตกลงสำหรับตัวอย่างของคุณ):
gawk 'BEGIN {for (i = 1; i < ARGC; i++) printf "%-3s|\n", ARGV[i]}
' u ü $'u\u308' $'\u1100'
หากเอาต์พุตไปที่เทอร์มินัลคุณสามารถใช้ลำดับการหลีกเลี่ยงตำแหน่งเคอร์เซอร์ได้ ชอบ:
forward21=$(tput cuf 21)
printf '%s\r%s%s\n' \
"Früchte und Gemüse" "$forward21" "foo" \
"Milchprodukte" "$forward21" "bar" \
"12345678901234567890" "$forward21" "baz"