---
title: 'Sıralama, Tekilleştirme ve Birleştirme'
source: 'https://academia.sh/tr/kurslar/kabuk-programlama/siralama-tekillestirme-ve-birlestirme'
course: 'Kabuk Programlama'
language: tr
updated: '2026-08-17T18:10:03+00:00'
license: 'CC BY-SA 4.0'
---

# Sıralama, Tekilleştirme ve Birleştirme

Anahtara göre sıralama, yerel ayarın sıralama düzenine etkisi, komşuluk gerektiren tekilleştirme ve sıralı akışlar üzerinde küme işlemleri.

Önceki derslerde her sayım `sort` ile bitirildi ama komutun kendisi açıklanmadı. Sıralama,
kabuk metin işlemenin en çok çağrılan ikinci aracıdır ve iki nedenle ayrı bir ders hak
eder: seçenekleri sonucu tümüyle değiştirir ve yanındaki üç araç — tekilleştirme,
karşılaştırma, birleştirme — girdilerinin sıralı olmasına dayanır.

Algoritmalar kursunda sıralamanın maliyeti ve kararlılık ölçütü tanımlanmıştı. Bu ders o
kavramları bir komutun seçeneklerine bağlar.

## Sözlük Sırası ve Sayısal Sıra

Öntanımlı karşılaştırma **sözlük sırasıdır**: değerler karakter karakter karşılaştırılır.

```sh
printf '10\n9\n100\n2\n' | sort
```

```
10
100
2
9
```

```sh
printf '10\n9\n100\n2\n' | sort -n
```

```
2
9
10
100
```

Sözlük sırasında `10`, `9`'dan önce gelir çünkü ilk karakteri `1`, `9`'dan küçüktür.
Sayıların sıralandığı her yerde `-n` gerekir; unutulması, raporların en sık görülen
sessiz hatasıdır.

`-r` sırayı tersine çevirir. `-n -r` birlikte, çoktan aza sıralamanın standart yazımıdır.

## Anahtar Tanımı

`-k` seçeneği, karşılaştırmanın hangi alan üzerinden yapılacağını belirtir. Yazımı
`-k başlangıç,bitiş` biçimindedir ve **bitişin yazılması zorunludur**: `-k2` yazımı
"ikinci alandan satır sonuna kadar" anlamına gelir, `-k2,2` yalnızca ikinci alanı seçer.

```sh
awk '{ print $7, $10 }' erisim.log | sort -k2,2n | head -3
```

```
/eski-sayfa 0
/giris 0
/statik/stil.css 0
```

Sayısal kip anahtara da eklenebilir: `-k2,2n` yazımı yalnızca o anahtar için geçerlidir.
Birden çok `-k` verilirse anahtarlar sırayla uygulanır ve ilk eşitlikte sonraki anahtara
geçilir.

`-t` ayırıcıyı belirler. Öntanımlı ayırıcı, alan tabanlı araçtan farklıdır: boşluk
kümesinden **boşluk olmayana geçiş** noktası ayırıcı sayılır.

```sh
printf 'c:3\na:1\nb:2\n' | sort -t: -k2,2n
```

```
a:1
b:2
c:3
```

## Kararlılık

Sıralama öntanımlı olarak **kararlı değildir**: eşit anahtarlı satırların göreli sırası
korunmaz. Eşitlik durumunda son çare olarak satırın tamamı karşılaştırılır.

```sh
printf 'b 1\na 1\nc 0\n' | sort -k2,2n
```

```
c 0
a 1
b 1
```

```sh
printf 'b 1\na 1\nc 0\n' | sort -s -k2,2n
```

```
c 0
b 1
a 1
```

`-s` seçeneği son çare karşılaştırmasını kapatır ve girdi sırasını korur. Çok anahtarlı
sıralamalarda — önce şehre, sonra kararlı biçimde tarihe göre — Algoritmalar kursunda
gösterilen kararlılık gereksinimi bu seçenekle karşılanır.

## Yerel Ayar

Karşılaştırma düzeni, çalışma ortamının yerel ayarına bağlıdır.

```sh
printf 'a\nB\nb\nA\n' | LC_ALL=C sort
```

```
A
B
a
b
```

```sh
printf 'a\nB\nb\nA\n' | LC_ALL=en_US.UTF-8 sort
```

```
a
A
b
B
```

İlk düzen bayt değerine göre, ikincisi harf temeline göre sıralar. İkisi de doğrudur;
sorun, hangisinin uygulanacağının betiği çalıştıran ortama bağlı olmasıdır.

Bu, betiklerde yeniden üretilemez sonuçların başlıca kaynağıdır. Aynı betik iki makinede
farklı sıralı çıktı verir; bir çıktıyı diğeriyle karşılaştıran bir sınama, gerçek bir fark
olmadığı hâlde başarısız olur.

Kural: **betikte sıralama yapılıyorsa yerel ayar açıkça sabitlenir.**

```sh
LC_ALL=C sort ...
```

`LC_ALL=C` bayt sırasını seçer; hızlıdır, öngörülebilirdir ve makineler arasında aynıdır.
İnsan okuyucu için harf temelli sıra isteniyorsa yerel ayar yine açıkça yazılmalıdır —
belirsiz bırakılmamalıdır.

Ayrıca `sort -u` ve `uniq` gibi işlemler "eşitlik" tanımını yerel ayardan aldığı için,
farklı ayarlarda farklı sayıda satır üretebilir. Sabitleme bu nedenle yalnızca sıra
meselesi değildir.

## Tekilleştirme

`uniq`, **komşu** yinelenen satırları teke indirir. Sıralanmamış girdide beklendiği gibi
çalışmaz:

```sh
printf 'a\nb\na\n' | uniq -c
printf 'a\nb\na\n' | sort | uniq -c
```

```
   1 a
   1 b
   1 a
   2 a
   1 b
```

İlk çağrıda hiçbir şey birleştirilmedi çünkü yinelenen `a` satırları komşu değildi. Bu,
kursun ilk konusundan beri kullanılan `sort | uniq -c` deseninin gerekçesidir.

Seçenekler farklı soruları yanıtlar:

| Seçenek | Çıktı |
|---|---|
| `-c` | her satırın önüne yineleme sayısı |
| `-d` | yalnızca birden çok kez geçen satırlar |
| `-u` | yalnızca bir kez geçen satırlar |
| `-i` | büyük–küçük harf ayrımsız karşılaştırma |

```sh
printf 'a\nb\nb\nc\n' | uniq -u
```

```
a
c
```

`sort -u` ile `sort | uniq` aynı sonucu verir ama `sort -u` daha ucuzdur: ayrı bir süreç
yaratılmaz. `uniq -c` gerekiyorsa iki adım zorunludur, çünkü `sort -u` sayım yapmaz.

## Küme İşlemleri

`comm`, **iki sıralı dosyayı** karşılaştırır ve üç sütun üretir: yalnızca birincide
olanlar, yalnızca ikincide olanlar, ikisinde de olanlar. `-1`, `-2`, `-3` seçenekleri ilgili
sütunu bastırır.

Kütüğün ilk ve son on beş satırında istenen yolları karşılaştıralım. İki dosya da
tekilleştirilmiş ve aynı yerel ayarla sıralanmış olarak hazırlanır:

```sh
export LC_ALL=C
head -15 erisim.log | cut -d' ' -f7 | sort -u > dun.txt
tail -15 erisim.log | cut -d' ' -f7 | sort -u > bugun.txt
```

```sh
comm -23 dun.txt bugun.txt      # yalniz birincide
```

```
/giris
```

```sh
comm -13 dun.txt bugun.txt      # yalniz ikincide
```

```
/eski-sayfa
```

```sh
comm -12 dun.txt bugun.txt      # ortak
```

```
/api/veri
/gizli
/index.html
/panel
/statik/stil.css
/urun/12
/urun/45
/yok.html
```

Üç çağrı sırasıyla küme farkını, ters farkı ve kesişimi verir. İki dosya da sıralı
olmalıdır ve **aynı yerel ayarla** sıralanmış olmalıdır; aksi hâlde `comm` uyarı verir ya
da sessizce yanlış sonuç üretir.

Bu araç, iki kütüğü karşılaştırmanın doğrudan yoludur: hangi yollar yalnızca bu dönemde
istendi, hangi istemciler kayboldu, hangi hata kodları yeni ortaya çıktı.

`join`, iki sıralı dosyayı ortak bir **anahtar alanı** üzerinden birleştirir; ilişkisel
veritabanlarındaki birleştirme işleminin metin karşılığıdır.

Yol başına istek sayısını ve toplam baytı iki ayrı dosyada üretip anahtarlarına göre
sıralayalım:

```sh
awk '{ sayim[$7]++ }     END { for (y in sayim) print y, sayim[y] }' erisim.log | sort -k1,1 > adet.txt
awk '{ bayt[$7] += $10 } END { for (y in bayt)  print y, bayt[y]  }' erisim.log | sort -k1,1 > boyut.txt
join adet.txt boyut.txt | head -5
```

```
/api/veri 6 7236
/eski-sayfa 1 0
/giris 1 0
/gizli 2 580
/index.html 4 20480
```

Öntanımlı olarak her iki dosyanın birinci alanı anahtar sayılır; `-1` ve `-2` seçenekleri
alan numarasını değiştirir, `-t` ayırıcıyı belirler. Girdilerin **anahtar alanına göre**
sıralı olması zorunludur — satırın tamamına göre değil. Bu ayrım, `join` kullanımındaki en
sık hatanın kaynağıdır.

## Belirlenimci Sıralama

Sayım çıktılarında eşit sayılı satırların sırası, son çare karşılaştırmasına ve yerel
ayara bağlıdır. Bu, raporun her çalıştırmada aynı çıkmasını engelleyebilir:

```sh
cut -d' ' -f7 erisim.log | sort | uniq -c | sort -rn | head -5
```

```
   6 /api/veri
   4 /yok.html
   4 /index.html
   3 /urun/45
   3 /urun/12
```

İkincil anahtar açıkça verildiğinde sonuç belirlenimci olur: önce sayıya göre azalan,
eşitlikte ada göre artan.

```sh
cut -d' ' -f7 erisim.log \
  | LC_ALL=C sort | uniq -c | LC_ALL=C sort -k1,1nr -k2,2 | head -5
```

```
   6 /api/veri
   4 /index.html
   4 /yok.html
   3 /panel
   3 /statik/stil.css
```

Eşit sayılı satırlar artık alfabetik sırada. Çıktısı sınanacak ya da iki çalıştırma
arasında karşılaştırılacak her betikte bu yazım kullanılmalıdır.

## Betiğe Uygulama

`rapor.sh` iki değişiklik alır. Birincisi, tüm sıralamaların yerel ayarı sabitlenir ve
ikincil anahtar verilir:

```sh
export LC_ALL=C

en_cok() {                      # en_cok ALAN DOSYA ADET
  local alan="$1" dosya="$2" adet="$3"
  cut -d' ' -f"$alan" "$dosya" | sort | uniq -c | sort -k1,1nr -k2,2 | head -"$adet"
}
```

`export LC_ALL=C` betiğin başına konur; böylece çağrılan tüm araçlar aynı düzeni kullanır.
Bu, betiğin çıktısını çalıştırıldığı ortamdan bağımsız kılar.

İkincisi, iki kütüğü karşılaştıran bir seçenek eklenir:

```sh
karsilastir() {                 # karsilastir ESKI YENI
  local eski="$1" yeni="$2"
  cut -d' ' -f7 "$eski" | sort -u > "$gecici/eski"
  cut -d' ' -f7 "$yeni" | sort -u > "$gecici/yeni"
  bolum "Yalnizca yeni kutukte gorulen yollar"
  comm -13 "$gecici/eski" "$gecici/yeni"
}
```

Bu fonksiyon geçici dosyalara yazıyor ve onları temizlemiyor. Sağlam Betik Yazımı
konusunda `mktemp` ve tuzaklarla bu eksik giderilecek.

## Özet

- Öntanımlı karşılaştırma sözlük sırasıdır; sayısal veride `-n` zorunludur.
- `-k başlangıç,bitiş` anahtarı sınırlar; bitiş yazılmazsa anahtar satır sonuna uzanır.
- Sıralama öntanımlı olarak kararlı değildir; `-s` son çare karşılaştırmasını kapatır.
- Karşılaştırma düzeni yerel ayara bağlıdır; betiklerde `LC_ALL=C` ile sabitlenmelidir.
- `uniq` yalnızca komşu yinelemeleri birleştirir; `sort | uniq -c` deseni bu yüzden
  ayrılmazdır.
- `comm` ve `join` sıralı girdi ister; ilki küme işlemleri, ikincisi anahtar üzerinden
  birleştirme yapar.

## Sonraki Adım

Bu konudaki araçların hepsi satır düzeyinde çalıştı. Sütun düzeyinde kesme, iki dosyayı
yan yana yapıştırma ve büyük bir kütüğü parçalara bölme ayrı bir araç öbeği gerektirir.
Sonraki ders bu öbeği ele alır ve metin işleme konusunu, hangi işin hangi araca ait
olduğunu belirleyen bir seçim ölçütüyle kapatır.
