ความซับซ้อนที่ซ่อนอยู่ของการเรียงลำดับแบบง่าย: ทำไม macOS และ Linux จึงเรียงลำดับไฟล์แตกต่างกัน

ทีมชุมชน BigGo
ความซับซ้อนที่ซ่อนอยู่ของการเรียงลำดับแบบง่าย: ทำไม macOS และ Linux จึงเรียงลำดับไฟล์แตกต่างกัน

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

ปัญหาหลัก: การเรียงลำดับที่ขึ้นอยู่กับโลเคล

หัวใจของความแตกต่างในการเรียงลำดับอยู่ที่ตัวแปรสภาพแวดล้อม LC_COLLATE ซึ่งกำหนดวิธีการเปรียบเทียบและจัดเรียงสตริง เมื่อนักพัฒนาทำการดำเนินการเรียงลำดับโดยคาดหวังพฤติกรรมที่สม่ำเสมอ across platforms พวกเขามักจะประหลาดใจที่พบว่า python3-dev มาอันดับก่อน python-dev บน Linux แต่มาอันดับหลังบน macOS แม้จะใช้การตั้งค่า locale เดียวกัน นี่ไม่ใช่ข้อบกพร่อง—แต่เป็นการออกแบบโดยเจตนาที่สะท้อนถึงแนวทางที่แตกต่างกันในการทำให้เป็นสากล

การเรียงลำดับมีความเฉพาะเจาะจงตามภาษา แม้ว่าคุณจะถูกจำกัดให้ใช้ภาษาที่ใช้ตัวอักษรละติน คุณจะเรียงลำดับ N กับ Ñ อย่างไร? คุณจะจัดการกับตัวอักษร I รูปแบบต่างๆ ในภาษาตุรกีอย่างไร?

ความคิดเห็นดังกล่าวเน้นย้ำความจริงพื้นฐาน: การเรียงลำดับไม่ใช่แค่การเปรียบเทียบค่าไบต์ ภาษาที่ต่างกันมีกฎที่แตกต่างกันสำหรับสิ่งที่ถือเป็นลำดับตัวอักษรที่ถูกต้อง และกฎเหล่านี้ต้องถูกเข้ารหัสไว้ somewhere

ตัวแปรสภาพแวดล้อมสำคัญสำหรับการควบคุมการเรียงลำดับ:

  • LC_COLLATE: กำหนดกฎการเรียงลำดับ (sorting)
  • LC_ALL: แทนที่การตั้งค่า locale ทั้งหมด
  • การตั้งค่า LC_ALL=C บังคับให้ใช้การเรียงลำดับตามค่าไบต์เพื่อให้มีพฤติกรรมที่สอดคล้องกันข้ามแพลตฟอร์ม

แนวทางแบบง่ายของ macOS

การตรวจสอบพฤติกรรมการเรียงลำดับของ macOS เผยให้เห็นการนำไปใช้ที่ตรงไปตรงมาอย่างน่าประหลาดใจ locale ส่วนใหญ่บน macOS รวมถึง en_US.UTF-8 ในที่สุดแล้วจะชี้ไปยังกฎการเรียงลำดับแบบ Latin (la_LN) ซึ่งโดยพื้นฐานแล้วจะทำการเปรียบเทียบค่าไบต์แบบง่ายๆ แนวทางนี้ย้อนกลับไปถึง FreeBSD 5.0 จากช่วงต้นปี 2000 ซึ่ง Apple ได้นำมาผนวกไว้ใน macOS และยังคงรักษาไว้ด้วยเหตุผลด้านความเข้ากันได้นับตั้งแต่นั้นมา

สมาชิกในชุมชนได้ยืนยันว่าความพยายามที่จะแทนที่ข้อมูล locale ของ macOS ด้วยการนำไปใช้ที่ทันสมัยกว่าจะทำให้แอปพลิเคชันที่มีอยู่ซึ่งพึ่งพาความแปลกประหลาดเหล่านี้ทำงานผิดปกติ แนวคิด if it ain't broke, don't fix it ยังคงมีอยู่ แม้ว่าการนำไปใช้ในปัจจุบันจะขาดความซับซ้อนสำหรับข้อความที่ไม่ใช่ภาษาอังกฤษก็ตาม นี่อธิบายว่าทำไมนักพัฒนาจึงมักหันไปใช้การตั้งค่า LC_COLLATE=C เพื่อให้ได้พฤติกรรมที่สม่ำเสมอ ซึ่งเป็นการ bypass การเรียงลำดับที่คำนึงถึง locale ไปโดยสิ้นเชิง

โซลูชันที่ครอบคลุมของ Linux

ในทางตรงกันข้ามกับความเรียบง่ายของ macOS การกระจาย Linux โดยทั่วไปจะใช้ระบบ locale ของ glibc ซึ่งนำมาตรฐาน ISO 14651 ที่ครอบคลุมสำหรับการเรียงลำดับสตริงสากลมาใช้ ข้อกำหนดนี้มีความยาวกว่า 85,000 บรรทัดที่อุทิศให้กับการกำหนดกฎการเรียงลำดับที่จัดการกับความซับซ้อนของภาษาทั่วโลกได้อย่างเหมาะสม มาตรฐานนี้คำนึงถึงความแตกต่างทางภาษาศาสตร์ที่การเปรียบเทียบไบต์แบบง่ายๆ ไม่สามารถทำได้ เช่น การปฏิบัติต่อการรวมตัวของอักขระบางอย่างเป็นหน่วยเดียวสำหรับวัตถุประสงค์ในการเรียงลำดับ

ภาษาเดนมาร์กเป็นตัวอย่างที่สมบูรณ์แบบของเหตุผลที่ว่าทำไมการเรียงลำดับที่ซับซ้อนจึงสำคัญ ดังที่ผู้แสดงความคิดเห็นคนหนึ่งระบุไว้ ก่อนที่จะนำตัวอักษร å มาใช้ในปี 1948 ภาษาเดนมาร์กใช้ aa สำหรับเสียงเดียวกัน ในการเรียงลำดับภาษาเดนมาร์กสมัยใหม่ å จะปรากฏที่ส่วนท้ายของตัวอักษร ซึ่งหมายความว่า Aarhus ควรจะถูกเรียงลำดับหลังจาก Odense อย่างถูกต้อง แม้ว่าจะขึ้นต้นด้วย Aa ก็ตาม ความแม่นยำทางภาษาศาสตร์ในระดับนี้เป็นไปไม่ได้ด้วยแนวทางการเปรียบเทียบไบต์แบบง่ายๆ ของ macOS

การเปรียบเทียบแพลตฟอร์ม:

แพลตฟอร์ม แหล่งที่มาของ Collation เริ่มต้น แนวทาง
macOS ยุค FreeBSD 5.0 (ทศวรรษ 2000) การเปรียบเทียบค่าไบต์แบบง่าย
Linux (glibc) มาตรฐาน ISO 14651 กฎทางภาษาศาสตร์ (มากกว่า 85,000 บรรทัด)

ผลกระทบในโลกจริงและวิธีแก้ปัญหา

ผลกระทบของความแตกต่างในการเรียงลำดับเหล่านี้ขยายออกไปไกลเกินกว่าความสนใจทางวิชาการ ผู้ดูแลฐานข้อมูลที่อัปเกรด PostgreSQL ได้พบกับปัญหาที่เกี่ยวข้องกับการเรียงลำดับซึ่งทำให้การโยกย้ายข้อมูลซับซ้อนขึ้น นักพัฒนาเว็บที่รวมระบบกับระบบ legacy อย่าง AS/400 ได้เผชิญกับความไม่ตรงกันในการเรียงลำดับที่ทำให้แอปพลิเคชันทำงานผิดปกติ แม้แต่ผู้เขียนสคริปต์ shell ก็ต้องตั้งค่า LC_COLLATE=C อย่างชัดเจนเพื่อให้แน่ใจว่าลำดับการโหลด plugin จะสม่ำเสมอ

นักพัฒนาคนหนึ่งแบ่งปันวิธีแก้ปัญหาในทางปฏิบัติ: ใน Zsh startup ของฉันบน Mac ฉันต้องกังวลเกี่ยวกับการเรียงลำดับ เนื่องจากฉันคาดหวังให้ ~ ถูกเรียงลำดับเป็นอันสุดท้าย ฉันต้องการ LC_COLLATE=C เพื่อให้มันเรียงลำดับตามที่คาดหวัง วิธีแก้ไขปัญหานี้ปรากฏบ่อยครั้งในการอภิปราย ซึ่งเน้นย้ำว่ามืออาชีพจำนวนมากได้พบและจัดการกับความแตกต่างของแพลตฟอร์มนี้อย่างไร

ตัวอย่างการเรียงลำดับในโลกจริง:

  • macOS: python-dev แล้วตามด้วย python3-dev (ลำดับไบต์: '-' มาก่อน '3')
  • Linux: python3-dev แล้วตามด้วย python-dev (กฎทางภาษาศาสตร์)
  • เมืองในเดนมาร์ก: Albertslund, Odense, Aarhus (การจัดการ 'å' อย่างถูกต้อง)

การถกเถียงที่ยังคงดำเนินอยู่: อะไรคือการเรียงลำดับที่ ถูกต้อง?

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

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

สรุป

ความแตกต่างในการเรียงลำดับระหว่าง macOS และ Linux ทำหน้าที่เป็นเครื่องเตือนใจว่าแม้แต่งานคอมพิวเตอร์ที่ดูเหมือนง่ายก็สามารถมีความซับซ้อนที่น่าประหลาดใจได้ สิ่งที่ดูเหมือนเป็นการเรียงลำดับตามตัวอักษรพื้นฐาน จริงๆ แล้วเกี่ยวข้องกับงานการทำให้เป็นสากลที่สะสมมาหลายทศวรรษ การตัดสินใจเฉพาะแพลตฟอร์ม และความท้าทายอย่างต่อเนื่องในการสร้างสมดุลระหว่างประสิทธิภาพกับความถูกต้องทางภาษาศาสตร์ สำหรับนักพัฒนาที่ทำงาน across platforms ความเข้าใจใน LC_COLLATE และการรู้ว่าจะใช้ LC_ALL=C เมื่อใด ยังคงเป็นความรู้ที่จำเป็นในโลกดิจิทัลของเราที่มีความเป็นโลกาภิวัตน์มากขึ้นเรื่อยๆ

อ้างอิง: The macOS LC_COLLATE hunt