เหตุใดการเรียงลำดับของ ls จึงไม่สนใจอักขระที่ไม่ใช่ตัวอักษรและตัวเลข


25

เมื่อเรียงลำดับชื่อไฟล์ละเว้นตัวอักษรเช่นls -,_ฉันคาดว่าจะใช้ตัวละครเหล่านั้นในการจัดเรียงเช่นกัน

ตัวอย่าง:

touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2

ตอนนี้แสดงไฟล์เหล่านี้ด้วยls -1:

a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2

สิ่งที่ฉันคาดหวังคืออะไรเช่นนี้:

a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2

นั่นคือฉันคาดหวังว่าจะต้องคำนึงถึงอักขระที่ไม่ใช่ตัวอักษรและตัวเลขเมื่อเรียง

มีใครอธิบายพฤติกรรมนี้ได้บ้าง พฤติกรรมนี้ได้รับคำสั่งจากมาตรฐานหรือไม่? หรือนี่เป็นเพราะการเข้ารหัสเป็น UTF-8

อัปเดต:ดูเหมือนว่าสิ่งนี้เกี่ยวข้องกับการเรียงลำดับ UTF-8:

$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

2
UTF-8 และ ASCII เหมือนกันถ้าทั้งหมดที่คุณใช้คือ 128 codepoints แรก (ซึ่งเป็นตัวอย่างของคุณ) จะเกิดอะไรขึ้นถ้าคุณทำLC_COLLATE=C ls?
Alexios

ปัญหาไม่ใช่ว่า ASCII และ UTF-8 เหมือนกัน แต่ค่อนข้างที่ UTF-8 มีกฎการเรียง (การเรียงลำดับ) ของตัวเอง
daniel kullmann

1
ใช่มันเป็นความจริงที่[_-,.]ถูกจัดกลุ่มและไม่สนใจกึ่ง ผมไม่ทราบว่าวิธีการหรือที่การเปรียบเทียบดังกล่าวถูกกำหนดไว้ แต่มันจะต้องเป็นประเด็นเปรียบเทียบเพราะเพียงและมีเพียงการเปลี่ยนการเปรียบเทียบเพื่อC (ผ่านLC_COLLATE=C ls -l) ก็เพียงพอที่จะทำให้คุณมีลำดับการจัดเรียงที่คุณคาดหวัง (สมมติว่าLC_ALLเป็น ไม่เอาชนะLC_COLLATE) สิ่งนี้ถือเป็นจริงสำหรับตัวละครทุกช่วงใน Unicode Basic Multilingual Plane ... ฉันได้แก้ไขคำตอบของฉันให้รวมสคริปต์ตัวอย่างที่ให้สิ่งนี้ออกมา ...
Peter.O

หากคุณไม่ชอบวิธีการทำงานคุณสามารถสร้างชื่อแทนและใส่ไว้ใน ~ / .profile: alias ls = 'LC_COLLATE = C ls' </kbd>
jippie

คำตอบ:


10

สิ่งนี้ไม่เกี่ยวกับชุดอักขระ แต่เป็นภาษาที่กำหนดลำดับการเรียง libc ตรวจสอบภาษาที่แสดงใน$LC_COLLATE/ $LC_ALL/ $LANGและค้นหากฎการจัดเรียง (เช่น/usr/share/i18n/locales/*GLibC) และเรียงลำดับข้อความตามที่ได้รับคำสั่ง


FYI: มันซับซ้อนกว่านี้ หากมีการใช้strcollตัวอย่างเช่นคุณจะเห็นอะไรบางอย่างที่เหมือนจะถูกจัดเรียงไว้ข้างต้นaasa.c aas.c
Don Scott

12

แก้ไข: เพิ่มการทดสอบสำหรับข้อมูลที่เรียงลำดับด้วย LC_COLLATE = C


ลำดับการเรียงเริ่มต้นคือการรักษาอักขระ "เครื่องหมายวรรคตอนประเภท" ว่ามีค่าเท่ากัน .. Use LC_COLLATE=Cเพื่อปฏิบัติตามลำดับ codepoint

for i in 'a1' 'a_1' 'a-1' 'a,1' 'a.1' 'a2' 'a_2' 'a-2' 'a,2' 'a.2' ;do
  echo $i; 
done |LC_COLLATE=C sort

เอาท์พุต

a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

รหัสต่อไปนี้การทดสอบทั้งหมดที่ถูกต้อง UTF-8 ตัวอักษรในภาษาเครื่องบินขั้นพื้นฐาน (ยกเว้น\ x00และ\ X0A ; สำหรับความเรียบง่าย)
จะเปรียบเทียบไฟล์ในที่รู้จักกัน (สร้าง) ลำดับจากน้อยไปมากกับแฟ้มที่เรียงแบบสุ่มและจัดเรียงแล้วอีกครั้งกับ LC_COLLATE = C ผลลัพธ์แสดงว่าลำดับCนั้นเหมือนกับลำดับที่สร้างขึ้นดั้งเดิม

{ i=0 j=0 k=0 l=0
  for i in {0..9} {A..F} ;do
  for j in {0..9} {A..F} ;do
  for k in {0..9} {A..F} ;do
  for l in {0..9} {A..F} ;do
     (( 16#$i$j$k$l == 16#0000 )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l == 16#000A )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#D800    && 
        16#$i$j$k$l <= 16#DFFF )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#FFFE )) && { printf '.' >&2; continue; }
     echo 0x"$i$j$k$l" |recode UTF-16BE/x4..UTF-8 || { echo "ERROR at codepoint $i$j$k$l " >&2; continue; } 
     echo 
  done
  done
  done; echo -n "$i$j$k$l " >&2
  done; echo >&2
} >listGen

             sort -R listGen    > listRandom
LC_COLLATE=C sort    listRandom > listCsort 

diff <(cat listGen;   echo "last line of listOrig " ) \
     <(cat listCsort; echo "last line of listCsort" )
echo 
cmp listGen listCsort; echo 'cmp $?='$?

เอาท์พุท:

63485c63485
< last line of listOrig 
---
> last line of listCsort

cmp $?=0

2
เอกสารนั้นอยู่ที่ไหน เป็นส่วนหนึ่งของมาตรฐาน Unicode หรือไม่?
daniel kullmann

2
ที่จริงแล้วพวกเขาไม่ได้รับค่าเดียวกัน อักขระเหล่านั้นจะถูกละเว้นเพียงเมื่อเรียงลำดับ หากพวกเขาได้รับการปฏิบัติเหมือนมีค่าเท่ากันการเรียงลำดับa_1 a2 a_2จะเป็นไปไม่ได้
daniel kullmann

+1 สำหรับการทำงานหนักและโค้ดตัวอย่างของคุณ หลังจากผ่านไปหลายชั่วโมงการเรียงลำดับชื่อไดเรกทอรีด้วยเครื่องหมายวรรคตอนเพื่อให้ตรงกับวิธีtreeฉันคิดว่ามีเรื่องราวมากขึ้นเช่นการลบเครื่องหมายวรรคตอนออกจากสตริงเปรียบเทียบหรืออะไรทำนองนั้น ฉันสามารถพูดได้ว่า/ตัวละครจะต้องถูกกำหนดให้เป็นตัวละครที่ต่ำที่สุดในลำดับการเรียงไม่ว่าจะมีอะไรอีก
WinEunuuchs2Unix
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.