---
title: 'Metin İşlevleri'
source: 'https://academia.sh/tr/kurslar/elektronik-tablolar/metin-islevleri'
course: 'Elektronik Tablolarla Analiz'
language: tr
updated: '2026-08-17T18:08:42+00:00'
license: 'CC BY-SA 4.0'
---

# Metin İşlevleri

48 saha ziyareti kaydı 60 abonelik listeyle abone kodu üzerinden eşleştiriliyor ve ham hâlinde yalnız 8'i tutuyor. Kırpma 24'e, kırpmayla birlikte büyük harfe çevirme 32'ye, her tür boşluğu silmek 48'e çıkarıyor; rapor edilen ziyaret tüketimi bu kararlarla 232,1 m³ ile 1204,8 m³ arasında oynuyor. Kodu yeniden kuran beşinci karar aynı 48'i verirken başka bir önekle gelen kaydı sessizce yanlış aboneye bağlıyor. Dil duyarsız harf dönüşümü teknisyen adlarının 15'ini tutturamıyor ve aynı sonucu üreten üç yazımdan yalnız birinde 40 düzeltme kararı hücre hücre geri okunabiliyor.

Buraya kadar her karşılaştırma sayısaldı. Sayfanın öteki yarısı metindir ve metinde eşitlik
sayıdaki kadar açık değildir: `AB-1041` ile `AB-1041 ` ekranda aynı görünür, aynı uzunlukta
görünmez ve karşılaştırıldığında eşit çıkmaz. Bu ders saha ziyareti kayıtlarını abone
listesiyle abone kodu üzerinden eşleştirir ve kaç kaydın **birleşmediğini** sayar.

Ölçü iki yerde okunur. Birincisi eşleşen kayıt sayısı ve onunla birlikte rapora giren tüketim
değeridir. İkincisi temizleme kararının nerede durduğudur: bir yardımcı sütunda mı, eşleştirme
formülünün içinde mi, yoksa hiçbir yerde mi — çünkü elle düzeltilmiş bir hücre sonucu doğru
gösterir ve kararı yok eder.

- **TT13.** Ziyaret tablosundaki abone kodları altı biçimde gelir: temiz, sonunda boşluk,
  başında boşluk, küçük harfli, sonunda **görünmeyen boşluk**, ortasında boşluk. Bozulmalar
  kurgudur ve kendi tohumuyla sırayla dağıtılır. Bozulmanın türü sayfada **yazmaz**; aşağıdaki
  `tur` işlevi onu ancak inceleyerek sınıflandırır.
- **TT14.** `kirp` işlevi yalnız **normal boşluğu** siler; görünmeyen boşluk ile iç boşluk
  kırpılmadan kalır. `temizle` her tür boşluğu siler. İkisi arasındaki fark bu dersin en pahalı
  kararıdır.
- **TT15.** `buyuk` dil duyarsız bir harf dönüşümüdür; `buyuktr` Türkçenin i harfi kuralını
  uygular. Ekip adları kurgudur ve yarısı küçük harfle girilmiştir.

## Gözle Aynı, Karşılaştırmada Farklı

Aşağıdaki blok iki tabloyu kurar: soldaki 60 abonelik liste, sağdaki 48 ziyaret kaydı. Çıktıda
boşluklar görünür karakterlere çevrilir — normal boşluk alt çizgi, görünmeyen boşluk tilde.

```js
// metin.mjs — elektronik tablo MODELI: 01'in modeli, metin islevleriyle genisletilmis.
// Saha ziyaretleri tablosundaki abone kodlari bozuk gelir; bozulmalar kurgudur.
export const TOHUM = 20260602, SATIR = 60, ZIYARET = 48;
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };
export const GB = "\u00a0";           // gorunmeyen bosluk: hucrede normal boslukla ayni

const REF = /(\$?)([A-Z])(\$?)(\d+)/g;
export const kaydir = (f, dS, dR) => f.replace(REF, (_, a, s, b, r) =>
  (a ? "$" + s : String.fromCharCode(s.charCodeAt(0) + dS)) + (b ? "$" + r : String(+r + dR)));

// Metin islevleri. buyuk dil duyarsizdir; buyuktr Turkce i/I kuralini uygular.
const ISLEV = {
  kirp: (s) => String(s).replace(/^ +| +$/g, ""),     // yalniz normal bosluk kirpilir
  buyuk: (s) => String(s).toUpperCase(),
  buyuktr: (s) => String(s).replace(/i/g, "İ").replace(/ı/g, "I").toUpperCase(),
  temizle: (s) => String(s).replace(/\s/g, ""),      // \s gorunmeyen boslugu da kapsar
  birlestir: (...p) => p.map(String).join(""),
  sagdan: (s, n) => String(s).slice(-n),             // sondan n karakter: kodun sayi kismi
  uzunluk: (s) => String(s).length,
};
export function deger(H, ad) {
  const v = H[ad];
  if (v === undefined) return 0;
  if (typeof v !== "string" || v[0] !== "=") return v;
  const ifade = v.slice(1).replace(REF, (m) => JSON.stringify(deger(H, m.replace(/\$/g, ""))));
  return Function(...Object.keys(ISLEV), `return (${ifade});`)(...Object.values(ISLEV));
}

// Alti bozulma turu; sayfada gozle ayirt edilemezler.
export const BOZ = [["temiz", (k) => k], ["sondaki bosluk", (k) => k + " "],
  ["bastaki bosluk", (k) => " " + k], ["kucuk harf", (k) => k.toLowerCase()],
  ["gorunmeyen bosluk", (k) => k + GB], ["ic bosluk", (k) => k.replace("-", "- ")]];
export const EKIP = ["İsmet", "İlknur", "Irmak", "Ilgaz", "Sedef"];

export function sayfa() {
  const r = uretec(TOHUM), H = {};
  H.A1 = "abone"; H.C1 = "tuketim"; H.P1 = "ziyaret kodu"; H.Q1 = "teknisyen";
  for (let i = 0; i < SATIR; i++) {
    const s = i + 2;
    H["A" + s] = "AB-" + String(1041 + i * 7).padStart(4, "0");
    r();                                    // 01'deki bolge sutunu: uretec ayni sirada calisir
    H["C" + s] = Math.round((2 + r() * r() * 78) * 10) / 10;
  }
  // Ziyaret tablosu: ZIYARET ayri abone, her bozulma turu sirayla uygulanir.
  const z = uretec(TOHUM + 2);
  const sira = Array.from({ length: SATIR }, (_, i) => i);
  for (let i = SATIR - 1; i > 0; i--) { const j = Math.floor(z() * (i + 1));
    [sira[i], sira[j]] = [sira[j], sira[i]]; }
  for (let i = 0; i < ZIYARET; i++) {
    const s = i + 2, k = H["A" + (2 + sira[i])];
    H["P" + s] = BOZ[i % BOZ.length][1](k);
    // Yarisi kucuk harfle girilmis; kucuk harfe cevirme Turkce kurala gore yapilir.
    const t = EKIP[Math.floor(z() * EKIP.length)];
    H["Q" + s] = z() < 0.5 ? t.replace(/İ/g, "i").replace(/I/g, "ı").toLowerCase() : t;
  }
  return H;
}

// Bozulmanin turu sayfada yazmaz; ancak inceleyerek siniflandirilir.
export const tur = (k) => k !== k.replace(/^ +| +$/g, "") ? "kirpilir bosluk"
  : k.includes(GB) ? "gorunmeyen bosluk" : k.includes("- ") ? "ic bosluk"
  : k !== k.toUpperCase() ? "kucuk harf" : "temiz";

if (import.meta.url === `file://${process.argv[1]}`) {
  const H = sayfa();
  const gor = (s) => String(s).replace(new RegExp(GB, "g"), "~").replace(/ /g, "_");
  const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
    : String(v).padEnd(B[0]))).join("");
  const y = g([8, 14, 8, 20]);
  console.log(y(["hucre", "ziyaret kodu", "uzunluk", "bozulma"]));
  for (const s of [2, 3, 4, 5, 6, 7]) console.log(y(["P" + s, gor(H["P" + s]),
    deger({ ...H, X1: "=uzunluk(P" + s + ")" }, "X1"), tur(H["P" + s])]));
  const P = Array.from({ length: ZIYARET }, (_, i) => H["P" + (i + 2)]);
  const K = new Set(Array.from({ length: SATIR }, (_, i) => H["A" + (i + 2)]));
  const sayim = {};
  for (const k of P) sayim[tur(k)] = (sayim[tur(k)] ?? 0) + 1;
  console.log(`\n${ZIYARET} ziyaret kaydi — ` +
    Object.entries(sayim).map(([a, n]) => `${a} ${n}`).join(", "));
  console.log(`Kodu abone tablosunda oldugu gibi bulunan kayit: ${P.filter((k) => K.has(k)).length}`);
}
```

```
hucre     ziyaret kodu uzunluk             bozulma
P2             AB-1286       7               temiz
P3            AB-1083_       8     kirpilir bosluk
P4            _AB-1167       8     kirpilir bosluk
P5             ab-1090       7          kucuk harf
P6            AB-1097~       8   gorunmeyen bosluk
P7            AB-_1048       8           ic bosluk

48 ziyaret kaydi — temiz 8, kirpilir bosluk 16, kucuk harf 8, gorunmeyen bosluk 8, ic bosluk 8
Kodu abone tablosunda oldugu gibi bulunan kayit: 8
```

Uzunluk sütunu dersin tek görünür kanıtıdır. `P3` ile `P6` sekiz karakterdir ve ikisinde de
sekizinci karakter bir boşluktur; ama biri kırpılır, öteki kırpılmaz. Sayfada ikisi de yedi
karakterlik bir kod gibi görünür. **Bir metin hücresinin gösterdiği şey, içerdiği şey
değildir.**

Ham hâlinde 48 kaydın yalnız 8'i abone listesinde bulunuyor. Kalan 40 kayıt kaybolmuş
abonelere ait değil; hepsi listede duran abonelere ait ve hiçbiri eşleşmiyor.

## Dört Temizleme Kararı

Temizleme tek bir işlem değil, sıralı kararlardır ve her karar bir grup kaydı geri getirir.
Aşağıdaki blok dördünü yardımcı bir `R` sütununda uygular ve her aşamada eşleşen kayıt sayısıyla
rapora girecek tüketimi basar.

```js
// eslesme.mjs — dort temizleme karari, dort eslesme sayisi ve dort rapor edilen tuketim.
import { sayfa, deger, kaydir, SATIR, ZIYARET } from "./metin.mjs";

const KARAR = [
  ["ham", "=P2"],
  ["kirpma", "=kirp(P2)"],
  ["kirpma + buyuk harf", "=buyuk(kirp(P2))"],
  ["her bosluk + buyuk harf", "=buyuk(temizle(P2))"],
  ["yeniden kurma", '=birlestir("AB-",sagdan(temizle(P2),4))'],
];
const H = sayfa();
const TUKETIM = new Map(Array.from({ length: SATIR }, (_, i) =>
  [H["A" + (i + 2)], H["C" + (i + 2)]]));
const anahtar = (f) => { const K = { ...H };
  for (let i = 0; i < ZIYARET; i++) K["R" + (i + 2)] = kaydir(f, 0, i);
  return Array.from({ length: ZIYARET }, (_, i) => deger(K, "R" + (i + 2))); };
const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");

const y = g([26, 10, 12, 14, 12]);
console.log(y(["R sutunu formulu", "eslesen", "eslesmeyen", "tuketim (m3)", "kurtarilan"]));
let onceki = 0;
for (const [ad, f] of KARAR) {
  const R = anahtar(f), e = R.filter((k) => TUKETIM.has(k));
  const t = e.reduce((a, k) => a + TUKETIM.get(k), 0);
  console.log(y([ad, e.length, ZIYARET - e.length, t.toFixed(1), e.length - onceki]));
  onceki = e.length;
}
const tam = Array.from({ length: SATIR }, (_, i) => H["C" + (i + 2)]).reduce((a, b) => a + b, 0);
console.log(`\n60 abonenin toplam tuketimi ${tam.toFixed(1)} m3; ziyaret edilen tuketim ` +
  `${anahtar(KARAR[3][1]).reduce((a, k) => a + (TUKETIM.get(k) ?? 0), 0).toFixed(1)} m3.`);

// Yeniden kurma kodu okumaz, yeniden yazar: baska bir onekle gelen kayit da eslesir.
const yad = { ...H, P2: "XY-1041" };
for (const [ad, f] of KARAR.slice(3)) {
  const K = { ...yad, R2: f };
  console.log(`${ad}: XY-1041 -> ${deger(K, "R2")} (${TUKETIM.has(deger(K, "R2")) ? "eslesti" : "eslesmedi"})`);
}
```

```
R sutunu formulu             eslesen  eslesmeyen  tuketim (m3)  kurtarilan
ham                                8          40         232.1           8
kirpma                            24          24         527.6          16
kirpma + buyuk harf               32          16         673.7           8
her bosluk + buyuk harf           48           0        1204.8          16
yeniden kurma                     48           0        1204.8           0

60 abonenin toplam tuketimi 1419.9 m3; ziyaret edilen tuketim 1204.8 m3.
her bosluk + buyuk harf: XY-1041 -> XY-1041 (eslesmedi)
yeniden kurma: XY-1041 -> AB-1041 (eslesti)
```

Rapora girecek sayı bu tablonun dördüncü sütununda ve dört değeri var: 232,1, 527,6, 673,7,
1204,8 m³. En küçüğü ile en büyüğü arasında beş kattan fazla fark var ve dördü de aynı veriden,
aynı soruyla, aynı gün çıktı. "Ziyaret edilen abonelerin toplam tüketimi" cümlesi tek başına bu
dört sayıdan hangisinin kastedildiğini söylemiyor.

Kırpma tek başına 16 kaydı geri getirdi ve orada durmak kolaydır: 24 eşleşme makul görünür,
kalan 24 kayıt da "listede olmayan aboneler" diye açıklanabilir. Oysa o 24 kaydın hepsi
listededir; 8'i görünmeyen boşluk, 8'i iç boşluk taşıyor ve ikisi de kırpmadan sağ çıkıyor.
**Bir temizlemenin yeterli olup olmadığı, temizlenmiş sayıya bakarak anlaşılamaz.**

Beşinci satır aynı sayıyı üçüncü bir yoldan veriyor ve en tehlikelisi odur. Yeniden kurma kodu
okumaz, **yeniden yazar**: sondan dört karakteri alıp başına sabit bir önek ekler. Son iki satır
bunun bedelini gösteriyor. Başka bir önekle gelen `XY-1041` kaydı dördüncü kararda eşleşmez,
beşinci kararda sessizce `AB-1041` olur ve ilgisiz bir aboneye bağlanır. Eşleşme sayısı aynı
kalır, hata görünmez.

## Harf Dönüşümü ve Kararın Yeri

Harf dönüşümü de tek bir işlem değildir. Aşağıdaki blok teknisyen adlarını iki dönüşümle
katlayıp ekip listesiyle karşılaştırır, ardından temizleme kararının sayfada nerede durduğunu
üç yazım üzerinde tarar.

```js
// karar.mjs — harf donusumunun dile bagliligi, ve temizleme kararinin sayfada nerede durdugu.
import { sayfa, deger, kaydir, EKIP, ZIYARET, GB } from "./metin.mjs";

const H = sayfa();
const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");
const sutun = (f, n) => { const K = { ...H };
  for (let i = 0; i < n; i++) K["S" + (i + 2)] = kaydir(f, 0, i);
  return Array.from({ length: n }, (_, i) => deger(K, "S" + (i + 2))); };

// Ekip listesi ayni islevle katlanir; eslesme iki katlanmis metnin esitligidir.
const y = g([30, 10, 12, 22]);
console.log(y(["S sutunu formulu", "eslesen", "eslesmeyen", "tutmayan ad"]));
for (const [ad, f] of [["dil duyarsiz", "=buyuk(Q2)"], ["Turkce kurali", "=buyuktr(Q2)"]]) {
  const S = sutun(f, ZIYARET);
  const liste = EKIP.map((t) => deger({ X1: "=" + f.slice(1).replace("Q2", JSON.stringify(t)) }, "X1"));
  const e = S.filter((v) => liste.includes(v)).length;
  const tut = [...new Set(S.filter((v) => !liste.includes(v)))].join(" ");
  console.log(y([ad + " (" + f + ")", e, ZIYARET - e, tut || "-"]));
}

// Ayni sonucu ureten uc yazim: karar yardimci sutunda, formulde ya da hic yok.
const YAZIM = [
  ["yardimci sutun", 'R sutunu =buyuk(temizle(P2))', ZIYARET, true],
  ["formule gomulu", "eslestirme formulu icinde", 0, true],
  ["elle duzeltme", "P sutunu uzerine yazilmis", 0, false],
];
const P = Array.from({ length: ZIYARET }, (_, i) => H["P" + (i + 2)]);
const bozuk = P.filter((k) => k !== k.replace(/^ +| +$/g, "") || k.includes(GB)
  || k.includes("- ") || k !== k.toUpperCase()).length;
const z = g([16, 30, 8, 10, 12]);
console.log("\n" + z(["yazim", "karar nerede", "hucre", "ham veri", "geri okuma"]));
for (const [ad, yer, hucre, ham] of YAZIM)
  console.log(z([ad, yer, hucre, ham ? "duruyor" : "silindi", hucre ? bozuk : 0]));
console.log(`\n${ZIYARET} ziyaret kaydinin ${bozuk} tanesi bozuk. Yardimci sutunda bu ${bozuk} ` +
  `karar tek tek okunur; elle duzeltmede hicbiri okunmaz ve ham kod da kalmaz.`);
```

```
S sutunu formulu                 eslesen  eslesmeyen           tutmayan ad
dil duyarsiz (=buyuk(Q2))             33          15          ISMET ILKNUR
Turkce kurali (=buyuktr(Q2))          48           0                     -

yazim                             karar nerede   hucre  ham veri  geri okuma
yardimci sutun    R sutunu =buyuk(temizle(P2))      48   duruyor          40
formule gomulu       eslestirme formulu icinde       0   duruyor           0
elle duzeltme        P sutunu uzerine yazilmis       0   silindi           0

48 ziyaret kaydinin 40 tanesi bozuk. Yardimci sutunda bu 40 karar tek tek okunur; elle duzeltmede hicbiri okunmaz ve ham kod da kalmaz.
```

Birinci tablo harf dönüşümünün bir metin işlemi değil, bir **dil** işlemi olduğunu yazıyor. Dil
duyarsız dönüşüm 48 adın 33'ünü tutturdu; tutmayan 15'i iki ada ait. Küçük harfle girilen
"ismet" ve "ilknur" adlarının baş harfi, dil duyarsız dönüşümde noktasız bir I'ya çevriliyor ve
listedeki noktalı biçimle eşleşmiyor. Türkçe kuralını uygulayan dönüşümde 48 adın hepsi tutuyor.
Aynı işlevin adı ikisinde de "büyük harfe çevir"dir; yaptıkları iş aynı değildir.

İkinci tablo dersin ikinci sayısını veriyor. Üç yazımın da eşleşme sonucu aynıdır: 48 kayıt
eşleşir. Ayrım son üç sütundadır. Yardımcı sütun yazımında karar 48 hücrede durur; temizlenmiş
kod görülebilir, ham kod da yerinde kalır ve bozuk gelen 40 kaydın her biri için "ne yapıldı"
sorusu hücreye bakılarak cevaplanır. Formüle gömülü yazımda sonuç aynıdır ama temizlenmiş kod
sayfada hiçbir yerde görünmez; hangi ziyaretin hangi aboneye bağlandığı yalnız formül metni
okunarak tahmin edilebilir.

Üçüncü satır en pahalı olanıdır ve en yaygın olanıdır. Kodlar elle düzeltilip `P` sütununun
üzerine yazıldığında sayfa kusursuz görünür: bütün kodlar temizdir, bütün eşleşmeler tutar,
hiçbir yardımcı sütun yoktur. Geri okunabilen karar sayısı **sıfırdır** ve ham veri de artık
yoktur. İkinci kez bakan biri 40 kaydın düzeltildiğini göremez, hangi kuralın uygulandığını
bilemez ve düzeltmenin doğru olup olmadığını denetleyemez. **Sonucu düzelten bir işlem, kararı
yok ediyorsa veriyi de yok eder.**

## Özet

- Metin hücresinin gösterdiği şey içerdiği şey değildir: aynı görünen iki kod farklı uzunlukta
  olabilir ve karşılaştırmada eşit çıkmaz.
- 48 ziyaret kaydının ham hâlinde 8'i eşleşti; kırpma 24'e, harf dönüşümü 32'ye, her tür boşluğun
  silinmesi 48'e çıkardı. Rapor edilen tüketim 232,1 ile 1204,8 m³ arasında oynadı.
- Sıradan kırpma yalnız normal boşluğu siler; görünmeyen boşluk ve iç boşluk taşıyan 16 kayıt
  kırpmadan sağ çıkar ve eşleşmemeye devam eder.
- Bir temizlemenin yettiği, temizlenmiş sayıya bakarak anlaşılmaz; ancak eşleşmeyen kayıtların
  tek tek incelenmesiyle anlaşılır.
- Harf dönüşümü dile bağlıdır: dil duyarsız dönüşüm 48 adın 15'ini tutturamadı, Türkçe kuralını
  uygulayan dönüşüm hepsini tutturdu.
- Aynı eşleşmeyi üreten üç yazımdan yalnız birinde 40 düzeltme kararı hücre hücre okunur; elle
  düzeltmede hem karar hem ham veri kaybolur.

## Sonraki Adım

Eşleştirme kurulduğuna göre ziyaret kayıtlarının tarihleri de kullanılabilir hâle geldi. Bir
sonraki adım basit görünen bir soruyu soruyor: bir arıza kaydının açılışıyla kapanışı arasında
kaç gün geçti. Tarih hücrede bir sayıdır ve gösterilen biçim o sayının kendisi değildir; iki
tarihin farkı bir çıkarma işlemidir, ama uçların dahil edilip edilmeyeceği bir karardır. Sonraki
ders aynı kayıt kümesinin ortalama çözüm süresini iki uç kararıyla hesaplar, bir ay sonrasının
ay sonunda ne anlama geldiğini ölçer ve metin olarak yazılmış tarihlerin kaçının iki farklı güne
okunabildiğini sayar.
