“ LC_ALL = C” ทำอะไร


324

สิ่งที่มีCคุณค่าสำหรับการLC_ALLทำในระบบเหมือน Unix?

ฉันรู้ว่ามันบังคับให้สถานที่เดียวกันทุกด้าน แต่จะCทำอย่างไร?


หากคุณต้องการแก้ไขปัญหาด้วยxclockคำเตือน ( Missing charsets in String to FontSet conversion) จะดีกว่าถ้าคุณจะใช้LC_ALL=C.UTF-8เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับไซริลลิก ในการตั้งค่าตัวแปรสภาพแวดล้อมนี้คุณต้องเพิ่มบรรทัดต่อไปนี้ที่ท้าย~/.bashrcไฟล์ -export LC_ALL=C.UTF-8
fedotsoldier

@Fedotsoldier คุณน่าจะถามคำถามและตอบด้วยตัวเองฉันไม่คิดว่ามันเกี่ยวข้องกับคำถาม เป็นเพียงคำตอบสำหรับปัญหาที่แตกต่างที่คุณมี
jcubic

ใช่คุณพูดถูก ok
fedotsoldier

คำตอบ:


209

มันบังคับให้แอปพลิเคชันใช้ภาษาเริ่มต้นสำหรับเอาต์พุต:

$ LC_ALL=es_ES man
¿Qué página de manual desea?

$ LC_ALL=C man
What manual page do you want?

และกองกำลังการเรียงลำดับให้เป็น byte-wise:

$ LC_ALL=en_US sort <<< $'a\nb\nA\nB'
a
A
b
B

$ LC_ALL=C sort <<< $'a\nb\nA\nB'
A
B
a
b

20
+1 สำหรับ exemples ดี แต่ขาดข้อมูลที่สำคัญที่อยู่ในคำตอบของสเตฟาน ...
โอลิเวีย Dulac

4
คุณหมายถึงอะไรโดยภาษาเริ่มต้น ?
Stéphane Chazelas

2
ใช่ฉันเข้าใจว่าผู้เขียนสามารถทำอะไรก็ได้ที่เขาชอบรวมถึงไม่ทำตามที่พูดไว้ สิ่งที่เป็น US English เป็นภาษาเดียวที่สามารถแสดงได้อย่างถูกต้องด้วยชุดอักขระใน LC_ALL = C ซึ่งเป็นภาษาเดียวที่ลำดับการเรียงใน LC_ALL = C (LC_COLLATE) มีเหตุผล LC_ALL = C (LC_TIME) มีชื่อเดือนและวันภาษาอังกฤษ ฉันไม่เคยเห็นแอปที่ LC_ALL = C แสดงข้อความเป็นภาษาอื่นจาก LC_ALL = th LANGUAGE = th ดังนั้นฉันจึงมีสิทธิ์รายงานข้อผิดพลาดกับโปรแกรมหากไม่ใช่กรณีนี้? (ไม่พูดถึงแอพที่ไม่ได้แปลเป็นภาษาอังกฤษที่นี่)
Stéphane Chazelas

2
ปัญหาคือ "ภาษาอังกฤษแบบสหรัฐอเมริกาเป็นภาษาเดียวที่สามารถแสดงได้อย่างถูกต้องด้วยชุดอักขระใน LC_ALL = C" สิ่งนี้มักเป็นจริงในโปรแกรม C / C ++ เมื่อใช้อักขระแคบ แต่ถึงแม้จะมีข้อยกเว้น (เนื่องจากมีหลายภาษาที่ใช้อักขระและสัญลักษณ์ที่พบใน ASCII เท่านั้น) การรายงานข้อผิดพลาดเมื่อภาษาเริ่มต้นไม่ใช่ภาษาอังกฤษจะทำให้คุณดูเหมือน ... เป็นเรื่องใหญ่
Ignacio Vazquez-Abrams

3
โปรดทราบว่าในภาษาอังกฤษ (หมายถึง LANG = en_US.utf8) ข้อความสามารถ (และควร) ใช้อักขระ unicode เช่น“” สำหรับการอ้างอิงสตริง ในขณะที่ LANG = C จะมีเพียง ASCII เท่านั้น (เครื่องหมายคำพูดคู่, backquotes และ apostrophes)
Ángel

332

LC_ALLเป็นตัวแปรสภาพแวดล้อมที่แทนที่การตั้งค่าการแปลอื่น ๆ ทั้งหมด ( ยกเว้นใน$LANGUAGEบางสถานการณ์ )

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

โดยทั่วไปคุณจะตั้ง$LANGค่าตามความชอบด้วยค่าที่ระบุภูมิภาคของคุณ (เช่นfr_CH.UTF-8ถ้าคุณใช้ภาษาสวิตเซอร์แลนด์ที่พูดภาษาฝรั่งเศสโดยใช้ UTF-8) LC_xxxตัวแปรแต่ละตัวจะแทนที่ด้านที่แน่นอน LC_ALLแทนที่พวกเขาทั้งหมด localeคำสั่งเมื่อเรียกโดยไม่มีข้อโต้แย้งให้บทสรุปของการตั้งค่าปัจจุบัน

ตัวอย่างเช่นในระบบ GNU ฉันได้รับ:

$ locale
LANG=en_GB.UTF-8
LANGUAGE=
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=

ฉันสามารถแทนที่การตั้งค่าส่วนบุคคลด้วยเช่น:

$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)

หรือ:

$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€

หรือแทนที่ทุกอย่างด้วย LC_ALL

$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory

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

Cสถานที่เกิดเหตุเป็นสถานที่พิเศษที่มีขึ้นเพื่อเป็นสถานที่ที่ง่ายที่สุด คุณสามารถพูดได้ว่าในขณะที่โลแคลอื่นสำหรับมนุษย์โลแคล C สำหรับคอมพิวเตอร์ ในโลแคล C อักขระจะเป็นไบต์เดียวชุดอักขระคือ ASCII (ไม่จำเป็นต้องใช้ แต่ในทางปฏิบัติจะอยู่ในระบบที่เราส่วนใหญ่จะใช้) ลำดับการเรียงจะขึ้นอยู่กับค่าไบต์ ภาษามักจะเป็นภาษาอังกฤษแบบสหรัฐอเมริกา (แม้ว่าจะมีข้อความของแอปพลิเคชัน (ตรงข้ามกับสิ่งต่าง ๆ เช่นชื่อเดือนหรือวันหรือข้อความจากไลบรารีระบบ) ขึ้นอยู่กับดุลยพินิจของผู้เขียนแอปพลิเคชัน) และสิ่งต่างๆเช่นสัญลักษณ์สกุลเงิน

ในบางระบบมีความแตกต่างกับโลแคล POSIX ที่ตัวอย่างการเรียงลำดับสำหรับอักขระที่ไม่ใช่ ASCII ไม่ได้ถูกกำหนดไว้

โดยทั่วไปคุณเรียกใช้คำสั่งด้วย LC_ALL = C เพื่อหลีกเลี่ยงการตั้งค่าของผู้ใช้เพื่อรบกวนสคริปต์ของคุณ ตัวอย่างเช่นถ้าคุณต้องการ[a-z]เพื่อให้ตรงกับอักขระ ASCII 26 จากaการที่คุณจะต้องตั้งค่าzLC_ALL=C

ในระบบ GNU, LC_ALL=CและLC_ALL=POSIX(หรือLC_MESSAGES=C|POSIX) แทนที่$LANGUAGEขณะที่LC_ALL=anything-elseจะไม่

บางกรณีที่คุณต้องตั้งค่าโดยทั่วไปLC_ALL=C:

  • sort -usort ... | uniq...หรือ ในสถานที่อื่น ๆ อีกมากมายกว่า C ในบางระบบ (สะดุดตาคน GNU) ตัวละครบางตัวมีการเรียงลำดับคำสั่งเดียวกัน sort -uไม่ได้รายงานบรรทัดที่ไม่ซ้ำกัน แต่หนึ่งในกลุ่มแต่ละบรรทัดที่มีลำดับการเรียงเท่ากัน ดังนั้นหากคุณต้องการบรรทัดที่ไม่ซ้ำกันคุณต้องมีสถานที่ที่ตัวละครเป็นไบต์และตัวละครทั้งหมดมีลำดับการจัดเรียงที่แตกต่างกัน (ซึ่งCสถานที่เกิดเหตุรับประกัน)
  • เช่นเดียวกับตัว=ดำเนินการที่เป็นไปตาม POSIX exprหรือ==ตัวดำเนินการของ POSIX ที่สอดคล้องawkกัน ( mawkและgawkไม่ใช่ POSIX ในเรื่องนั้น) ซึ่งไม่ได้ตรวจสอบว่ามีสองสตริงเหมือนกันหรือไม่
  • ช่วงตัวละครเหมือนgrepมา ถ้าคุณหมายถึงเพื่อให้ตรงกับตัวอักษรในภาษาของผู้ใช้ให้ใช้และไม่ได้ปรับเปลี่ยนgrep '[[:alpha:]]' LC_ALLแต่ถ้าคุณต้องการจับคู่a-zA-Zอักขระ ASCII คุณต้องการอย่างใดอย่างหนึ่งLC_ALL=C grep '[[:alpha:]]'หรือLC_ALL=C grep '[a-zA-Z]'¹ [a-z]จับคู่อักขระที่เรียงลำดับหลังaและก่อนหน้าz(แม้ว่าจะมี API หลายตัวมันก็ซับซ้อนกว่านั้น) ในสถานที่อื่น ๆ โดยทั่วไปคุณไม่รู้ว่ามันคืออะไร ยกตัวอย่างเช่นบางทำเลไม่สนใจกรณีสำหรับการเรียงลำดับดังนั้น[a-z]ใน APIs บางอย่างเช่นbashรูปแบบอาจรวมหรือ[B-Z] [A-Y]ในหลายพื้นที่ของ UTF-8 (รวมถึงen_US.UTF-8ระบบส่วนใหญ่) [a-z]จะรวมถึงตัวอักษรละตินจากaถึงyกับกำกับ แต่ไม่ใช่ของz(ตั้งแต่zเรียงลำดับก่อนหน้าพวกเขา) ซึ่งฉันไม่สามารถจินตนาการได้ว่าจะเป็นสิ่งที่คุณต้องการ (ทำไมคุณต้องการที่จะรวมéและไม่ได้ź)
  • ksh93ลอยเลขคณิตจุดใน ksh93เกียรตินิยมการตั้งค่าในdecimal_point LC_NUMERICหากคุณเขียนสคริปต์ที่มีa=$((1.2/7))มันจะหยุดทำงานเมื่อผู้ใช้ที่มีสถานที่เกิดเหตุมีเครื่องหมายจุลภาคเป็นตัวคั่นทศนิยม:

    $ ksh93 -c 'echo $((1.1/2))'
    0.55
    $ LANG=fr_FR.UTF-8  ksh93 -c 'echo $((1.1/2))'
    ksh93: 1.1/2: arithmetic syntax error
    

    จากนั้นคุณต้องการสิ่งต่าง ๆ เช่น:

    #! /bin/ksh93 -
    float input="$1" # get it as input from the user in his locale
    float output
    arith() { typeset LC_ALL=C; (($@)); }
    arith output=input/1.2 # use the dot here as it will be interpreted
                           # under LC_ALL=C
    echo "$output" # output in the user's locale
    

    ตามหมายเหตุด้านข้าง: ,ตัวคั่นทศนิยมขัดแย้งกับตัว,ดำเนินการทางคณิตศาสตร์ซึ่งอาจทำให้เกิดความสับสนมากยิ่งขึ้น

  • เมื่อคุณต้องการอักขระเป็นไบต์ ทุกวันนี้โลแคลส่วนใหญ่เป็นแบบ UTF-8 ซึ่งหมายความว่าตัวอักษรสามารถรับได้ตั้งแต่ 1 ถึง 6 ไบต์ เมื่อจัดการกับข้อมูลที่มีความหมายเป็นไบต์ด้วยยูทิลิตี้ข้อความคุณจะต้องตั้งค่า LC_ALL = C นอกจากนี้ยังจะปรับปรุงประสิทธิภาพอย่างมากเนื่องจากการแยกวิเคราะห์ข้อมูล UTF-8 มีค่าใช้จ่าย
  • ข้อสรุปของประเด็นก่อนหน้า: เมื่อประมวลผลข้อความที่คุณไม่ทราบว่าชุดอักขระที่ป้อนเข้านั้นถูกเขียนด้วยอะไร แต่สามารถสันนิษฐานได้ว่ามันเข้ากันได้กับ ASCII (ตามที่เป็นตัวอักษรทั้งหมด) ยกตัวอย่างเช่นgrep '<.*>'ที่จะมองหาเส้นที่มี<, >คู่จะไม่ทำงานถ้าคุณอยู่ในสถานที่เกิดเหตุ UTF-8 และการป้อนข้อมูลจะถูกเข้ารหัสในตัวเดียวอักขระไบต์ 8 บิตตั้งเช่น iso8859-15 นั่นเป็นเพราะการ.จับคู่เฉพาะอักขระและอักขระที่ไม่ใช่ ASCII ใน iso8859-15 มีแนวโน้มที่จะไม่สร้างอักขระที่ถูกต้องใน UTF-8 ในทางกลับกันLC_ALL=C grep '<.*>'จะทำงานได้เนื่องจากค่าไบต์ใด ๆ สร้างอักขระที่ถูกต้องในCโลแคล
  • เวลาใดก็ตามที่คุณประมวลผลข้อมูลอินพุตหรือข้อมูลเอาต์พุตที่ไม่ได้มีไว้สำหรับมนุษย์ หากคุณกำลังพูดคุยกับผู้ใช้คุณอาจต้องการใช้การประชุมและภาษาของพวกเขา แต่ตัวอย่างเช่นหากคุณสร้างตัวเลขเพื่อป้อนแอปพลิเคชันอื่น ๆ ที่คาดว่าจะได้รับทศนิยมสไตล์อังกฤษหรือชื่อเดือนภาษาอังกฤษ ตั้ง LC_ALL = C:

    $ printf '%g\n' 1e-2
    0,01
    $ LC_ALL=C printf '%g\n' 1e-2
    0.01
    $ date +%b
    août
    $ LC_ALL=C date +%b
    Aug
    

    นอกจากนี้ยังใช้กับสิ่งต่าง ๆ เช่นการเปรียบเทียบแบบไม่รู้สึกตัวพิมพ์เล็กและตัวพิมพ์ใหญ่grep -i( awk's toupper(), dd conv=ucase... ) ตัวอย่างเช่น

    grep -i i
    

    ไม่รับประกันว่าจะตรงกับIในภาษาของผู้ใช้ ในสถานที่ตุรกีบางตัวอย่างเช่นมันไม่ได้เป็นบนกรณีiคือİ(โปรดทราบจุด) และมีกรณีที่ต่ำกว่าIคือı(โปรดทราบจุดที่ขาดหายไป)


¹ขึ้นอยู่กับการเข้ารหัสของข้อความนั่นไม่ใช่สิ่งที่ถูกต้องที่จะทำ ถูกต้องสำหรับชุดอักขระ UTF-8 หรือไบต์เดียว (เช่น iso-8859-1) แต่ไม่จำเป็นต้องเป็นชุดอักขระแบบมัลติไบต์ UTF-8

ตัวอย่างเช่นหากคุณอยู่ในzh_HK.big5hkscsสถานที่ (ฮ่องกงใช้ตัวแปรฮ่องกงของการเข้ารหัสตัวอักษรจีน BIG5) และคุณต้องการค้นหาตัวอักษรภาษาอังกฤษในไฟล์ที่เข้ารหัสในชุดอักขระนั้นโดยทำดังนี้

LC_ALL=C grep '[[:alpha:]]'

หรือ

LC_ALL=C grep '[a-zA-Z]'

จะผิดเพราะในชุดอักขระนั้น (และอื่น ๆ อีกมากมาย แต่แทบจะไม่ได้ใช้ตั้งแต่ UTF-8 ออกมา) อักขระจำนวนมากประกอบด้วยไบต์ที่สอดคล้องกับการเข้ารหัส ASCII ของอักขระ A-Za-z ตัวอย่างทั้งหมดA䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽(และอื่น ๆ อีกมากมาย) Aมีการเข้ารหัสของ คือ 0x96 0x41 และA0x41 เช่นเดียวกับใน ASCII ดังนั้นเราLC_ALL=C grep '[a-zA-Z]'จะจับคู่กับบรรทัดเหล่านั้นที่มีอักขระเหล่านั้นเนื่องจากมันจะตีความลำดับของไบต์เหล่านั้นผิด

LC_COLLATE=C grep '[A-Za-z]'

จะใช้งานได้ แต่LC_ALLไม่ได้ตั้งค่าไว้เป็นอย่างอื่น (ซึ่งจะแทนที่LC_COLLATE) ดังนั้นคุณอาจต้องทำ:

grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'

หากคุณต้องการค้นหาตัวอักษรภาษาอังกฤษในไฟล์ที่เข้ารหัสในการเข้ารหัสของโลแคล


12
+1 เป็นคำตอบที่ดีที่สุด (สำหรับการชี้ให้เห็นถึงการเอาชนะ ฯลฯ ) แต่ขาดตัวอย่างคำตอบของอิกนาชิโอ (ดี) ^^
Olivier Dulac

1
nitpick ผู้เยาว์ที่: Cสถานที่เกิดเหตุจะต้องเฉพาะเพื่อสนับสนุน "ชุดอักขระแบบพกพา" (ASCII 0-127) และพฤติกรรมตัวอักษร> 127 คือไม่ระบุรายละเอียดทางเทคนิค ในทางปฏิบัติโปรแกรมส่วนใหญ่จะถือว่าเป็นข้อมูลทึบแสงและส่งผ่านตามที่คุณอธิบาย แต่ไม่ใช่ทั้งหมด: โดยเฉพาะทับทิมอาจสำลักข้อมูลถ่านด้วยไบต์> 127 หากทำงานในCโลแคล ฉันสุจริตไม่ทราบว่าในทางเทคนิค "สอดคล้อง" แต่เราได้เห็นมันในป่า
Andrew Janke

2
@AndrewJanke ใช่ โปรดทราบว่าชุดอักขระแบบพกพานั้นไม่ได้มีความหมายว่า ASCII หรือ 0-127 มีการถกเถียงกันมากมายในรายการส่งเมลกลุ่ม Austin ว่าคุณสมบัติของชุดอักขระโลแคล "C" จะเป็นอย่างไรและฉันทามติทั่วไป (และจะชี้แจงในสเป็คถัดไป) คือชุดอักขระนั้นจะเป็นแบบเดี่ยว - ไบต์และล้อมช่วง 8 บิตเต็ม (พร้อมคุณสมบัติอธิบายไว้ที่นี่) ในเวลาเฉลี่ยใช่อาจมีความแตกต่างบ้าง (เป็นข้อผิดพลาดหรือเนื่องจากข้อมูลจำเพาะไม่ชัดเจนเพียงพอ) ใน anycase LC_ALL = C นั้นใกล้เคียงที่สุดคุณจะได้รับพฤติกรรมที่มีสติ
Stéphane Chazelas

1
Unicode codepoint ใน UTF-8 สามารถมีได้สูงสุด 4 octets (หรือไบต์) แต่อักขระบางตัวต้องการ codepoint มากกว่าหนึ่งตัวซึ่งสามารถนำไปสู่ลำดับที่ยาวกว่า 6 octets
12431234123412341234123

1
@ 12431234123412341234123 การเข้ารหัส UTF-8 ดั้งเดิมครอบคลุม U + 7FFFFFFF (6 ไบต์และมีส่วนขยายบางส่วนที่จะไปถึง 13 ไบต์เช่นperl's \x{7FFFFFFFFFFFFFFF}) และในขณะที่ช่วงของจุดรหัส Unicode ถูก จำกัด โดยพลการ (เนื่องจากข้อ จำกัด ในการออกแบบ UTF-16) เครื่องมือบางอย่างยังคงรับรู้ / สร้างตัวอักษรขนาด 6 ไบต์ นั่นคือสิ่งที่ฉันหมายถึง 6 ตัวอักษรไบต์ ในซีแมนทิกส์ Unix อักขระหนึ่งตัวคือ codepoint หนึ่งตัว "อักขระ" codepointของคุณมากกว่าหนึ่งตัวถูกอ้างถึงโดยทั่วไปว่าเป็นกลุ่มกราฟเพื่อแยกแยะจากตัวละคร
Stéphane Chazelas

7

Cเป็นสถานที่เริ่มต้น "POSIX" เป็นนามแฝงของ "C" ฉันเดาว่า "C" มาจาก ANSI-C บางที ANSI-C จะกำหนดโลแคล "POSIX"


ทั้ง C และ UNIX นั้นลงวันที่ก่อนวันจริง ANSI C.
CVn

@ MichaelKjörling: งั้นเหรอ? ฉันเคยเห็นเอกสาร pre-ANSI มาก่อนแล้วและมันไม่มีตำแหน่งที่ตั้ง ภายในที่ AT&T Bell Labs ทุกคนพูดภาษาอังกฤษได้
MSalters

@MSalters ความจริงที่ว่าเอกสาร pre-ANSI สำหรับภาษา C ไม่ได้พูดถึงตำแหน่งที่ตั้ง (ซึ่งอาจหรืออาจไม่ได้หมายความว่า pre-ANSI, C ไม่มีแนวความคิดเกี่ยวกับตำแหน่งที่ตั้ง แต่ฉันค่อนข้างแน่ใจว่าภาษายังคงไม่ แต่นั่นคือสิ่งที่อยู่ข้างๆ) ไม่ได้หมายความว่าCชื่อสถานที่นั้นมาจาก "ANSI C"
CVn

2
@ MichaelKjörling: คุณไม่มีจุด เมื่อมีการแนะนำโลแคล "C" หมายถึง "ANSI C" แล้ว นั่นหมายถึง K&R C ในอดีตไม่เกี่ยวข้อง
MSalters

3

เท่าที่ฉันสามารถบอกได้ OS X ใช้ลำดับการเรียงโค้ดในโลแคล UTF-8 ดังนั้นจึงเป็นข้อยกเว้นสำหรับบางจุดที่กล่าวถึงในคำตอบโดยStéphane Chazelas

สิ่งนี้พิมพ์ 26 ใน OS X และ 310 ใน Ubuntu:

export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l

โค้ดด้านล่างไม่พิมพ์สิ่งใดใน OS X ซึ่งบ่งชี้ว่ามีการเรียงลำดับอินพุต อักขระตัวแทนหกตัวที่ถูกลบออกทำให้เกิดข้อผิดพลาดลำดับไบต์ที่ผิดกฎหมาย

export LC_ALL=en_US.UTF-8
for ((i=1;i<=0x1fffff;i++));do
  x=$(printf %04x $i)
  [[ $x = @(000a|d800|db7f|db80|dbff|dc00|dfff) ]]&&continue
  printf %b \\U$x\\n
done|sort -c

โค้ดด้านล่างไม่พิมพ์สิ่งใดใน OS X ซึ่งบ่งชี้ว่าไม่มีจุดรหัสต่อเนื่องสองจุด (อย่างน้อยระหว่าง U + 000B และ U + D7FF) ที่มีลำดับการเรียงเหมือนกัน

export LC_ALL=en_US.UTF-8
for ((i=0xb;i<=0xd7fe;i++));do
  printf %b $(printf '\\U%08x\\n' $((i+1)) $i)|sort -c 2>/dev/null&&echo $i
done

(ตัวอย่างข้างต้นใช้%bเพราะprintf \\U25ผลลัพธ์มีข้อผิดพลาดเป็น zsh)

อักขระบางตัวและลำดับของอักขระที่มีการเรียงลำดับเดียวกันในระบบ GNU ไม่มีลำดับการเรียงเหมือนกันใน OS X ซึ่งจะพิมพ์①เป็นอันดับแรกใน OS X (ใช้ OS X sortหรือ GNU sort) แต่เป็นครั้งแรกใน Ubuntu:

export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort

พิมพ์สามบรรทัดใน OS X (โดยใช้ OS X sortหรือ GNU sort) แต่หนึ่งบรรทัดใน Ubuntu:

export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u

ไม่มีใครรู้ว่าทำไมถึงมีความแตกต่างนี้
1.61803

3

ปรากฏว่าLC_COLLATEควบคุม "ลำดับตามตัวอักษร" ที่ใช้โดย ls เช่นกัน สถานที่ของสหรัฐอเมริกาจะเรียงลำดับดังนี้:

a.C
aFilename.C
aFilename.H
a.H

โดยทั่วไปจะไม่สนใจช่วงเวลา คุณอาจชอบ:

a.C
a.H
aFilename.C
aFilename.H

ฉันทำอย่างแน่นอน การตั้งค่าLC_COLLATEให้Cสำเร็จนี้ โปรดทราบว่ามันจะเรียงลำดับตัวพิมพ์เล็กหลังจากเมืองหลวงทั้งหมด:

A.C
A.H
AFilename.C
a.C
a.H
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.