การเพิ่มสตริง Unicode ด้วย bash's printf
ฉันลองขยายสตริง Unicode ด้วย printf ของ bash และเห็นว่าในขณะนั้น
printf "%2s" a
ให้ผล "a" ที่คาดหวัง
ตัวแปร Unicode
printf "%2s" ä
ให้ผลตอบแทน "ä" ที่ไม่มีการกดอย่างน่าประหลาดใจ (zsh ให้ผลลัพธ์ที่คาดหวัง)
สาเหตุนี้คืออะไร และฉันจะวางสตริง Unicode ใน bash ได้อย่างไร?
คำตอบ
ฉันจะวางสตริง Unicode ใน bash ได้อย่างไร
นั่นเป็นวิธีที่เกินความสามารถของ bash หากคุณกำลัง จำกัด "สตริง Unicode" ไว้ที่ ascii ++ (ไม่มีอักขระแบบ double width ไม่มี bidi ไม่มีเครื่องหมายไม่เว้นวรรค ฯลฯ ) คุณอาจตัดสินว่า:
% pad(){ printf '%*s%s\n' "$(($1-${#2}))" "" "$2"; }
% pad 2 €
€
อักขระäถูกเข้ารหัสด้วย 2 ไบต์ใน UTF-8 ดังนั้น Printf จึงใช้สำหรับ 2-padded
Wc สามารถนับอักขระ ( -m) และไบต์ ( -c) ของสตริง จำนวนที่จะให้ printf [intended pad]+[bytes]-[chars]เป็นแล้ว ดังนั้นฉันจึงรวบรวมpad.shสคริปต์นี้
#!/bin/sh
bytes=$(printf '%s' "$2" | wc -c)
chars=$(printf '%s' "$2" | wc -m)
n=$(($1+bytes-chars))
printf "%${n}s" "$2"
ในการดำเนินการตัวอย่างด้านล่างฉันได้เพิ่มบรรทัดใหม่หลังจากแต่ละเอาต์พุตเพื่อความชัดเจน
$ sh pad.sh 10 abcdef abcdef $ sh pad.sh 10 äéßôçÈ
äéßôçÈ
bash ทำงานอย่างถูกต้องและโปรแกรม C
#include <stdio.h>
main()
{
char foo[] = "ä";
printf("%2s\n", foo);
}
มีพฤติกรรมเหมือนกัน
เนื่องจาก% s อ้างถึงสตริงเชิงไบต์และ 'ä' ใน UTF-8 จะให้ผลลัพธ์เป็น 2 ไบต์
เท่าที่ฉันทดสอบได้ไม่มีเปลือกอื่นใดที่ทำงานผิดพลาด
ผลลัพธ์ที่คุณคาดหวังจะเห็นได้จากสิ่งต่างๆเช่น:
printf '%2S\n' ä
แต่สิ่งนี้ไม่ได้รับการสนับสนุนจากกระสุนใด ๆ ที่ฉันทดสอบ