İki alanda sıralama yapmaya çalışıyorum, önce ikinci, sonra ilk


106

Birden çok sütunda sıralamaya çalışıyorum. Sonuçlar beklendiği gibi değil.

İşte verilerim (people.txt):

Simon Strange 62
Pete Brown 37
Mark Brown 46
Stefan Heinz 52
Tony Bedford 50
John Strange 51
Fred Bloggs 22
James Bedford 21
Emily Bedford 18
Ana Villamor 44
Alice Villamor 50
Francis Chepstow 56

Aşağıdaki doğru çalışır:

bash-3.2$ sort -k2 -k3 <people.txt                                                                                                                    
Emily Bedford 18                                                                                                                                      
James Bedford 21                                                                                                                                      
Tony Bedford 50                                                                                                                                       
Fred Bloggs 22                                                                                                                                        
Pete Brown 37                                                                                                                                         
Mark Brown 46                                                                                                                                         
Francis Chepstow 56                                                                                                                                   
Stefan Heinz 52                                                                                                                                       
John Strange 51                                                                                                                                       
Simon Strange 62                                                                                                                                      
Ana Villamor 44                                                                                                                                       
Alice Villamor 50

Ancak, aşağıdaki beklendiği gibi çalışmaz:

bash-3.2$ sort -k2 -k1 <people.txt                                        
Emily Bedford 18                                                                                                                                      
James Bedford 21                                                                                                                                      
Tony Bedford 50                                                                                                                                       
Fred Bloggs 22                                                                                                                                        
Pete Brown 37                                                                                                                                         
Mark Brown 46                                                                                                                                         
Francis Chepstow 56                                                                                                                                   
Stefan Heinz 52                                                                                                                                       
John Strange 51                                                                                                                                       
Simon Strange 62                                                                                                                                      
Ana Villamor 44                                                                                                                                       
Alice Villamor 50

Soyadına ve sonra da ismine göre sıralamaya çalışıyordum, ama Villamorların doğru sırada olmadığını göreceksiniz. Soyadına göre sıralamayı umuyordum, sonra soyadları eşleştiğinde, ilk ada göre sıralamayı umuyordum.

Bunun nasıl çalışması gerektiğini anlamadığım bir şey var gibi görünüyor. Bunu başka bir yolla yapabilirim (awk kullanarak), ancak çeşitliliği anlamak istiyorum.

Mac OS X'te standart Bash kabuk kullanıyorum.

Yanıtlar:


159

Benzer bir özellik, -k2tüm alanları 2'den satırın sonuna kadar hesaba katmak anlamına gelir. Böylece daha Villamor 44önce biter Villamor 50. Bu ikisi eşit olmadığından, ilk karşılaştırma sort -k2 -k1bu iki satırı ayırt etmek için yeterlidir ve ikinci sıralama anahtarı -k1çağrılmaz. İki Villamors aynı yaşta -k1olsaydı, onların ilk isimlerine göre sıralanmasına neden olurdu.

Tek bir sütuna göre sıralamak için -k2,2, anahtar belirtimi kullanın . Bu, # 2'den # 2'ye kadar olan alanları, yani yalnızca ikinci alanı kullanmak anlamına gelir.

sort -k2 -k3 <people.txtgereksiz: buna eşdeğerdir sort -k2 <people.txt. Soyadlarına göre sıralamak için önce adlara, sonra yaşa, aşağıdaki komutu çalıştırın:

sort -k2,2 -k1,1 <people.txt

veya sort -k2,2 -k1 <people.txtsadece bu üç alan olduğundan ve ayırıcılar aynı olduğundan eşdeğerdir . Aslında, aynı etkiyi elde edersiniz sort -k2,2 <people.txt, çünkü bir sortsatır alt kümesindeki tüm anahtarlar aynı olduğunda tüm satırı son çare olarak kullanır.

Ayrıca, varsayılan alan ayırıcısının boş olmayan ve boş arasındaki bir geçiş olduğunu unutmayın; bu nedenle anahtarlar baştaki boşlukları içerecektir (örneğin, ilk satır için ilk anahtar olacak "Emily", ancak ikinci anahtar " Bedford". -bbu boşlukları sıyırma seçeneği:

sort -b -k2,2 -k1,1

bAnahtar başlangıç ​​belirtiminin sonuna bayrak ekleyerek anahtar başına da yapılabilir :

sort -k2b,2 -k1,1 <people.txt

Ancak akılda tutulması gereken bir şey: anahtar belirtime bu bayraklardan birini eklediğiniz anda, küresel bayraklar (örneğin -n, -r...) artık onlar için geçerli değildir, bu nedenle anahtar bayrakların ve dünya bayraklarının karışmasını önlemek daha iyidir.


6
Başardın. -K1 belirtmenin, alanın varsayılan alan ayırıcısında (boşluk) biteceği alan 1'i kullanması anlamına geldiğini (tehlikeli bir şey) varsaymıştım. Ancak açıkça belirttiğiniz gibi, k seçeneği sizden anahtarın başlangıç ​​ve bitiş noktalarını belirlemenizi bekler; bu, tek bir alan olabilir veya olmayabilir. Çözümünüz mükemmel çalışıyor ve daha da önemlisi, neden böyle olduğu konusunda netim. Çok teşekkürler.
Harry

Bu cok büyük. KEYDEF hakkındaki diğer birçok kaynak, her bir sıralama adımında hangi sütunların dikkate alınacağını sınırlama biçiminde COMMA'nın önemini vurgulamadan -k1 -k2 hakkında konuşur. Bu cevabı bulana kadar saatlerce buna takıldım. Ve adam sayfası burada kafa karıştırıcı. "Başlat ve durdur" konumlarının virgül notasyonu ile belirtildiğini açıklamıyor. Teşekkür ederim!
Jason Rohrer

16

GNU ile sortMacOS hakkında emin değilsiniz.

sort -k2,2 -k1 <people.txt

Yoruma göre güncelleyin . Gönderen man sort:

   -k, --key=KEYDEF
          sort via a key; KEYDEF gives location and type

   KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
   F is a field number and C a character position in the field; both are
   origin 1, and the stop position defaults to the line's end.

4
Lütfen bu garip gösterimi açıklar mısınız?
scai

1
Bu beni doğru çizgide düşündürdü - bunun için teşekkürler. Ancak ikinci -k için durma noktasını belirtmeniz gerekmez. Bu -k2,2 -k1,1, aksi halde durma noktası satır sonu olarak mı alınır?
Harry

@TonyBedford, doğru. Ancak durma pozisyonunu belirtmemek, mevcut girişinizin sonucunu değiştirmeyecek, ancak aynı alan 2 ve 1 ile aynı anda birden fazla satıra sahip olmanız durumunda tutarlılığı zorlayacaktır. Bu yüzden -k, sonuncunun olabildiğince dahil etmesine izin vermeyi tercih ediyorum .
Manat çalışması

1
@manatwork Bu gerekli olmamalıdır; belirtilen tüm alanların eşit sortkarşılaştırması varsa, tüm satırı karşılaştırır. Veya GNU ile kararlı sıralama için sortkullanabilirsiniz -s.
augurar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.