MySQL'de normal ifade nasıl değiştirilir?


515

~ 500k satır içeren bir tablo var; varchar (255) UTF8 sütunu filenamebir dosya adı içerir;

Ben dosya adı dışında çeşitli garip karakterler çıkarmaya çalışıyorum - bir karakter sınıfı kullanmak düşündüm: [^a-zA-Z0-9()_ .\-]

Şimdi, MySQL'de normal bir ifade ile değiştirmenize izin veren bir fonksiyon var mı? Basitleştirilmiş örnek aşağıdaki gibi REPLACE () işlevine benzer bir işlev arıyorum:

SELECT REPLACE('stackowerflow', 'ower', 'over');

Output: "stackoverflow"

/* does something like this exist? */
SELECT X_REG_REPLACE('Stackoverflow','/[A-Zf]/','-'); 

Output: "-tackover-low"

REGEXP / RLIKE hakkında biliyorum , ama bunlar sadece bir maç olup olmadığını kontrol ediyor , maçın ne olduğunu değil .

(I olabilir bir "do SELECT pkey_id,filename FROM foo WHERE filename RLIKE '[^a-zA-Z0-9()_ .\-]'" bir PHP komut dosyasından, bir do preg_replaceardından ve " UPDATE foo ... WHERE pkey_id=...", ancak böyle olduğu görünüyor yavaş ve çirkin kesmek son çare)


8
2007'den beri bir özellik isteği: bugs.mysql.com/bug.php?id=27389 . Bu özelliği gerçekten istiyorsanız, oturum açın ve "Beni etkiler" düğmesini tıklayın. Umarım yeterli oy alır.
TMS

4
@Tomas: Bunu yaptım ... 2009'da, etrafa bakarken. Üzerinde sıfır ilerleme olduğu için - görünüşe göre bu çok önemli bir özellik değil. (btw Postgres'de var: stackoverflow.com/questions/11722995/… )
Piskvor,

1
İlgili, daha basit, bu sorunun sürümü: stackoverflow.com/questions/6942973/…
Kzqai

2
Oluşturdum regexp_split(fonksiyon + prosedür) & regexp_replace, REGEXPoperatör ile uygulanır . Basit aramalar için işinizi görecektir. Burada bulabilirsiniz - bu yüzden, MySQL depolanmış kod, UDF yok. Bilinen sınırlamalar kapsamına girmeyen bazı hatalar bulursanız, sorunu açmaktan çekinmeyin.
Alma Do

1
Bu kütüphaneyi başka bir SO iş parçacığından buldum : github.com/mysqludf/lib_mysqludf_preg mükemmel çalışıyor.
Kyle

Yanıtlar:


77

MySQL 8.0+ ile yerel REGEXP_REPLACEişlevi kullanabilirsiniz .

12.5.2 Normal İfadeler :

REGEXP_REPLACE(expr, pat, repl[, pos[, occurrence[, match_type]]])

Yerini dize içinde oluşumları expre deseni ile belirtilen düzenli ifadeyi eşleştirmek pat yedek dize ile repl ve döner çıkan dize. Eğer expr , pat veya repl olduğu NULL, dönüş değeridir NULL.

ve Düzenli ifade desteği :

Daha önce, MySQL düzenli ifade operatörlerini ( REGEXP, RLIKE) desteklemek için Henry Spencer düzenli ifade kütüphanesini kullanıyordu .

Tam Unicode desteği sağlayan ve çok baytlı güvenli Uluslararası Unicode Bileşenleri (ICU) kullanılarak düzenli ifade desteği yeniden uygulanmıştır. REGEXP_LIKE()Fonksiyonu şekilde normal ifade eşleştirmesini gerçekleştirir REGEXPve RLIKEşimdi bu işlev için eş olan operatörler. Buna ek olarak, REGEXP_INSTR(), REGEXP_REPLACE()ve REGEXP_SUBSTR() işlevleri eşleme konumlarını bulmak için mevcuttur ve sırasıyla, ikame ve çıkarma substring gerçekleştirmek.

SELECT REGEXP_REPLACE('Stackoverflow','[A-Zf]','-',1,0,'c'); 
-- Output:
-tackover-low

DBFiddle Demosu


146

MySQL 8.0+ :

Yerel REGEXP_REPLACEişlevi kullanabilirsiniz .

Eski versiyonlar:

Mysql-udf-regexp gibi kullanıcı tanımlı bir işlev ( UDF ) kullanabilirsiniz .


3
Kullanıcı Tanımlı İşlev olarak REGEXP_REPLACE? Umut verici görünüyor, içine bakacağız. Teşekkürler!
Piskvor binadan ayrıldı

15
Maalesef mysql-udf-regexp'nin çok baytlı karakterler için desteği yok gibi görünüyor. regexp_replace ('äöõü', 'ä', ''), gerçek metin yerine uzun bir sayısal dize döndürür.
lkraav

3
MySQL, RegEx özellikleri ile çok baytlı karakterleri desteklemez.
Brad

4
Windows kullanıcıları: Buraya bağlanan UDF Kütüphanesi'nin iyi Windows desteği yok gibi görünüyor. Belirtilen windows kurulum yöntemi benim için iyi çalışmadı.
Jonathan

2
@lkraav harika çalıştığı için aşağıdaki lib_mysqludf_preg kütüphanesini denemelisiniz. Bu ayrıntılı sürümü varsayılan olarak bir blob döndürür ve varsayılan olarak çok baytlı bir setiniz olup olmadığını bilmiyorum: select cast (char olarak TR) COLLATE utf8_unicode_ci (select preg_replace ('/ ä /', '', 'öõüä') R) T
gillyspy

124

Bunun yerine MariaDB kullanın. Bir işlevi var

REGEXP_REPLACE(col, regexp, replace)

Bkz mariadb dokümanlar ve PCRE Düzenli ifade geliştirmeleri

Not regexp gruplama da kullanabilirsiniz (çok yararlı buldum):

SELECT REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '\\2 - \\1 - \\3')

İadeler

over - stack - flow

12
Bu mariadb 10
Nick

6
Bir dahaki sefere ihtiyacım olduğunda, tüm sütunu değiştirmek için sözdizimi: UPDATE table SET Name = REGEXP_REPLACE(Name, "-2$", "\\1")Bu, abcxyz-2'den -2'yi bir kerede tüm sütundan kaldırır.
Josiah

27
Tüm bir platformu değiştirmek neredeyse gerçekçi bir çözüm değildir.
David Baucum

3
@DavidBaucum MariaDB, MySQL için bir yedek yoldur. Yani "platform değişikliği" değil, aynı yolculuk için farklı bir havayolu seçmek gibi
Benvorth


113

Bu işe almak için kaba kuvvet yöntemi sadece:

  1. Masayı boşaltın - mysqldump -u user -p database table > dump.sql
  2. Birkaç desen bulun ve değiştirin - find /path/to/dump.sql -type f -exec sed -i 's/old_string/new_string/g' {} \;, Açıkçası dosyada da yapabileceğiniz diğer perl regeular ifadeleri var.
  3. Tabloyu içe aktarın - mysqlimport -u user -p database table < dump.sql

Dizenin veri kümenizin başka bir yerinde olmadığından emin olmak istiyorsanız, hepsinin benzer bir ortamda gerçekleştiğinden emin olmak için birkaç normal ifade çalıştırın. Ayrıca, bilgi derinliğini kaybeden bir şeyi yanlışlıkla yok etmeniz durumunda, bir yedek çalıştırmadan önce yedek oluşturmak da zor değildir.


33
Tamam, bu da işe yaramalı; Çevrimdışı değiştirmeyi düşünmedim. Güzel hazır düşünme orada!
Piskvor binadan ayrıldı

10
Böyle bulmak kullanmayı tercih ediyorum bana garip görünüyor, ben komutu kısaltılacak sed -i 's / old_string / new_string / g' /path/to/dump.sql
speshak

36
Çok riskli ve büyük veri kümeleriyle veya uygulama bütünlüğü yerinde değilse pratik değildir: verileri kaldırmak ve daha sonra tekrar eklemek için, veritabanınızı pratikte de bırakarak referans bütünlüğünü kapatmanız gerekecektir.
Raul Luna

5
Geçmişte bu yöntemi kullandıktan sonra Raul ile birleşiyorum, bu çok riskli. Dizenizin veri kümenizin başka bir yerinde olmadığından da kesinlikle emin olmanız gerekir.
yumurta pastası

1
Cevap @speshak'a yıllarca geçtim ama dosyaya bu şekilde erişmeyi tercih etmemin nedeni, yukarıda belirtilenlerle aynı nedenlerden dolayı çok gergin olmamdı. O zaman "dosyayı bul" bölümünü "değiştir" kısmından ayırmak, kodu göndermeden önce okumayı kolaylaştıracak gibi görünüyordu
Ryan Ward

42

regex kullanmadan bu sorunu yalnızca tam eşleme dizesinin yerini alıyoruz.

update employee set
employee_firstname = 
trim(REPLACE(concat(" ",employee_firstname," "),' jay ',' abc '))

Misal:

emp_id çalışan_firmaadı

1 alakarga

2 jay ajay

3 alakarga

Sorgu sonucunu yürüttükten sonra:

emp_id çalışan_firmaadı

1 abc

2 abc ajay

3 abc


@yellowmelon iki çift çift tırnak ne için?
codecowboy

5
Çalışan adını önce ve sonra boşluklarla dolduruyor. Bu onun (boşluk) çalışan adını (boşluk) aramasını ve değiştirmesini sağlar. Sonra bittiğinde boşlukları keser.
Slam

42

Son zamanlarda düzenli ifadeler kullanarak dizeleri değiştirmek için bir MySQL işlevi yazdım. Yazımı şu konumda bulabilirsiniz:

http://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/

İşlev kodu şöyledir:

DELIMITER $$

CREATE FUNCTION  `regex_replace`(pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN 
 DECLARE temp VARCHAR(1000); 
 DECLARE ch VARCHAR(1); 
 DECLARE i INT;
 SET i = 1;
 SET temp = '';
 IF original REGEXP pattern THEN 
  loop_label: LOOP 
   IF i>CHAR_LENGTH(original) THEN
    LEAVE loop_label;  
   END IF;
   SET ch = SUBSTRING(original,i,1);
   IF NOT ch REGEXP pattern THEN
    SET temp = CONCAT(temp,ch);
   ELSE
    SET temp = CONCAT(temp,replacement);
   END IF;
   SET i=i+1;
  END LOOP;
 ELSE
  SET temp = original;
 END IF;
 RETURN temp;
END$$

DELIMITER ;

Örnek yürütme:

mysql> select regex_replace('[^a-zA-Z0-9\-]','','2my test3_text-to. check \\ my- sql (regular) ,expressions ._,');

25
Ben sadece yukarıdaki noktayı güçlendireceğim: bu fonksiyon tek karakterli bir ifadeyle eşleşen karakterlerin yerine geçer . Yukarıda "düzenli ifadeler kullanarak dizeleri yeniden düzenlemek için" kullanıldığını ve bunun biraz yanıltıcı olabileceğini söylüyor. İşini yapıyor ama istenen iş değil. (Şikayet değil - sadece önde gelen insanları yanlış yolda kurtarmaktır)
Jason

2
Açık bir bağlantı göndermek yerine cevabınıza kodu dahil etmek daha yararlı olacaktır.
phobie

2
Güzel - ama ne yazık ki gibi referanslarla ilgilenmiyor select regex_replace('.*(abc).*','\1','noabcde')('abc' değil 'noabcde' döndürür).
Izzy

@fobie başka biri bu cevapta bunu yaptı - bağlantı koparsa bir referans olarak;)
Izzy

Yukarıda belirtilen sınırlamalardan bazılarını ve daha fazlasını ele almak için bu yöntemi değiştirdim. Lütfen bu cevaba bakınız .
Steve Chambers


13

GÜNCELLEME 2: MySQL 8.0'da REGEXP_REPLACE dahil olmak üzere yararlı normal ifade işlevleri seti sağlanmıştır. Bu, daha önceki bir sürümü kullanmakla sınırlı olmadığınız sürece okumayı gereksiz kılar.


GÜNCELLEME 1: Şimdi bunu bir blog yayınına dönüştürdüm: http://stevettt.blogspot.co.uk/2018/02/a-mysql-regular-expression-replace.html


Aşağıdakiler Rasika Godawatte tarafından sağlanan işlevi genişletir, ancak yalnızca tek karakterleri test etmek yerine gerekli tüm alt dizelerde dolaşır :

-- ------------------------------------------------------------------------------------
-- USAGE
-- ------------------------------------------------------------------------------------
-- SELECT reg_replace(<subject>,
--                    <pattern>,
--                    <replacement>,
--                    <greedy>,
--                    <minMatchLen>,
--                    <maxMatchLen>);
-- where:
-- <subject> is the string to look in for doing the replacements
-- <pattern> is the regular expression to match against
-- <replacement> is the replacement string
-- <greedy> is TRUE for greedy matching or FALSE for non-greedy matching
-- <minMatchLen> specifies the minimum match length
-- <maxMatchLen> specifies the maximum match length
-- (minMatchLen and maxMatchLen are used to improve efficiency but are
--  optional and can be set to 0 or NULL if not known/required)
-- Example:
-- SELECT reg_replace(txt, '^[Tt][^ ]* ', 'a', TRUE, 2, 0) FROM tbl;
DROP FUNCTION IF EXISTS reg_replace;
DELIMITER //
CREATE FUNCTION reg_replace(subject VARCHAR(21845), pattern VARCHAR(21845),
  replacement VARCHAR(21845), greedy BOOLEAN, minMatchLen INT, maxMatchLen INT)
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN 
  DECLARE result, subStr, usePattern VARCHAR(21845); 
  DECLARE startPos, prevStartPos, startInc, len, lenInc INT;
  IF subject REGEXP pattern THEN
    SET result = '';
    -- Sanitize input parameter values
    SET minMatchLen = IF(minMatchLen < 1, 1, minMatchLen);
    SET maxMatchLen = IF(maxMatchLen < 1 OR maxMatchLen > CHAR_LENGTH(subject),
                         CHAR_LENGTH(subject), maxMatchLen);
    -- Set the pattern to use to match an entire string rather than part of a string
    SET usePattern = IF (LEFT(pattern, 1) = '^', pattern, CONCAT('^', pattern));
    SET usePattern = IF (RIGHT(pattern, 1) = '$', usePattern, CONCAT(usePattern, '$'));
    -- Set start position to 1 if pattern starts with ^ or doesn't end with $.
    IF LEFT(pattern, 1) = '^' OR RIGHT(pattern, 1) <> '$' THEN
      SET startPos = 1, startInc = 1;
    -- Otherwise (i.e. pattern ends with $ but doesn't start with ^): Set start pos
    -- to the min or max match length from the end (depending on "greedy" flag).
    ELSEIF greedy THEN
      SET startPos = CHAR_LENGTH(subject) - maxMatchLen + 1, startInc = 1;
    ELSE
      SET startPos = CHAR_LENGTH(subject) - minMatchLen + 1, startInc = -1;
    END IF;
    WHILE startPos >= 1 AND startPos <= CHAR_LENGTH(subject)
      AND startPos + minMatchLen - 1 <= CHAR_LENGTH(subject)
      AND !(LEFT(pattern, 1) = '^' AND startPos <> 1)
      AND !(RIGHT(pattern, 1) = '$'
            AND startPos + maxMatchLen - 1 < CHAR_LENGTH(subject)) DO
      -- Set start length to maximum if matching greedily or pattern ends with $.
      -- Otherwise set starting length to the minimum match length.
      IF greedy OR RIGHT(pattern, 1) = '$' THEN
        SET len = LEAST(CHAR_LENGTH(subject) - startPos + 1, maxMatchLen), lenInc = -1;
      ELSE
        SET len = minMatchLen, lenInc = 1;
      END IF;
      SET prevStartPos = startPos;
      lenLoop: WHILE len >= 1 AND len <= maxMatchLen
                 AND startPos + len - 1 <= CHAR_LENGTH(subject)
                 AND !(RIGHT(pattern, 1) = '$' 
                       AND startPos + len - 1 <> CHAR_LENGTH(subject)) DO
        SET subStr = SUBSTRING(subject, startPos, len);
        IF subStr REGEXP usePattern THEN
          SET result = IF(startInc = 1,
                          CONCAT(result, replacement), CONCAT(replacement, result));
          SET startPos = startPos + startInc * len;
          LEAVE lenLoop;
        END IF;
        SET len = len + lenInc;
      END WHILE;
      IF (startPos = prevStartPos) THEN
        SET result = IF(startInc = 1, CONCAT(result, SUBSTRING(subject, startPos, 1)),
                        CONCAT(SUBSTRING(subject, startPos, 1), result));
        SET startPos = startPos + startInc;
      END IF;
    END WHILE;
    IF startInc = 1 AND startPos <= CHAR_LENGTH(subject) THEN
      SET result = CONCAT(result, RIGHT(subject, CHAR_LENGTH(subject) + 1 - startPos));
    ELSEIF startInc = -1 AND startPos >= 1 THEN
      SET result = CONCAT(LEFT(subject, startPos), result);
    END IF;
  ELSE
    SET result = subject;
  END IF;
  RETURN result;
END//
DELIMITER ;

gösteri

Rextester Demosu

Sınırlamalar

  1. Bu yöntem elbette konu dizesi büyük olduğunda biraz zaman alacaktır. Güncelleme: Artık bilindiği zaman verimliliği artırmak için minimum ve maksimum eşleşme uzunluğu parametreleri ekledik (sıfır = bilinmeyen / sınırsız).
  2. Bu olmaz geribaşvuruların (örn ikamesine imkan verir \1, \2 yakalama gruplarını değiştirmek için vs.). Bu işlevsellik gerekiyorsa, bulunan her bir eşleşme içinde (artan karmaşıklık pahasına) ikincil bir bulma ve değiştirme işlevini güncelleyerek bir geçici çözüm sağlamaya çalışan bu yanıta bakın .
  3. Eğer ^ve / veya $gibi mesela desenleri - desende kullanılan, çok başlatmak ve çok sırasıyla sona olmalıdır (^start|end$)desteklenmez.
  4. Genel eşleşmenin açgözlü veya açgözlü olmamasını belirten "açgözlü" bir bayrak vardır. Açgözlü ve tembel eşleşmeyi tek bir düzenli ifade (örneğin a.*?b.*) içinde birleştirmek desteklenmez.

Kullanım örnekleri

İşlev, aşağıdaki StackOverflow sorularını cevaplamak için kullanılmıştır:


7

Yapabilirsin ... ama çok akıllıca değil ... bu deneyeceğim kadar cüretkar ... tam RegEx kadar perl veya benzeri kullanarak çok daha iyi destek.

UPDATE db.tbl
SET column = 
CASE 
WHEN column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]' 
THEN REPLACE(column,'WORD_TO_REPLACE','REPLACEMENT')
END 
WHERE column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]'

1
Hayır, bu işe yaramaz. Sütununuzun 'asdfWORD_TO_REPLACE WORD_TO_REPLACE "içerdiğini düşünün. Yönteminiz doğru cevabın" asdfWORD_TO_REPLACE DEĞİŞTİRİLMESİ "olacağı' asdfREPLACEMENT REPLACEMENT" ile sonuçlanır.
Ryan Shillington

1
@Ryan ... tam da bu yüzden çok akıllıca olmadığını söyledim ... sağladığınız kullanım durumunda bu kesinlikle başarısız olur. Kısacası, 'normal ifade benzeri' yapıyı kullanmak kötü bir fikirdir. Daha da kötüsü ... nereye fıkra verirseniz tüm değerleriniz NULL olur ...
Eddie B

1
Aslında Ryan bu durumda yanılıyorsunuz çünkü işaretçiler yalnızca sıfır uzunluklu 'sınırlar' kelimesi için eşleşmeler bulacaktır, bu yüzden sadece kelimeden önce ve sonra sınırları olan kelimeler eşleşir ... Yine de kötü bir fikir ...
Eddie B

6

SELECT sorgusunda IF koşulunu aşağıdaki gibi kullanabiliriz:

"ABC", "ABC1", "ABC2", "ABC3", ... ile ilgili herhangi bir şey için, "ABC" ile değiştirmek ve ardından SELECT sorgusunda REGEXP ve IF () koşulunu kullanmak istediğimizi varsayalım. .

Sözdizimi:

SELECT IF(column_name REGEXP 'ABC[0-9]$','ABC',column_name)
FROM table1 
WHERE column_name LIKE 'ABC%';

Misal:

SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');

Merhaba, öneri için teşekkürler. Benzer bir şey deniyorum, ancak veri kümelerimdeki performans tatmin edici değil. Ufacık setler için bu uygulanabilir olabilir.
Piskvor binadan

3

Aşağıdaki maç temel olarak soldan ilk eşleşmeyi bulur ve ardından tüm tekrarlarını değiştirir ( ).

Kullanımı:

SELECT REGEX_REPLACE('dis ambiguity', 'dis[[:space:]]*ambiguity', 'disambiguity');

Uygulama:

DELIMITER $$
CREATE FUNCTION REGEX_REPLACE(
  var_original VARCHAR(1000),
  var_pattern VARCHAR(1000),
  var_replacement VARCHAR(1000)
  ) RETURNS
    VARCHAR(1000)
  COMMENT 'Based on https://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/'
BEGIN
  DECLARE var_replaced VARCHAR(1000) DEFAULT var_original;
  DECLARE var_leftmost_match VARCHAR(1000) DEFAULT
    REGEX_CAPTURE_LEFTMOST(var_original, var_pattern);
    WHILE var_leftmost_match IS NOT NULL DO
      IF var_replacement <> var_leftmost_match THEN
        SET var_replaced = REPLACE(var_replaced, var_leftmost_match, var_replacement);
        SET var_leftmost_match = REGEX_CAPTURE_LEFTMOST(var_replaced, var_pattern);
        ELSE
          SET var_leftmost_match = NULL;
        END IF;
      END WHILE;
  RETURN var_replaced;
END $$
DELIMITER ;

DELIMITER $$
CREATE FUNCTION REGEX_CAPTURE_LEFTMOST(
  var_original VARCHAR(1000),
  var_pattern VARCHAR(1000)
  ) RETURNS
    VARCHAR(1000)
  COMMENT '
  Captures the leftmost substring that matches the [var_pattern]
  IN [var_original], OR NULL if no match.
  '
BEGIN
  DECLARE var_temp_l VARCHAR(1000);
  DECLARE var_temp_r VARCHAR(1000);
  DECLARE var_left_trim_index INT;
  DECLARE var_right_trim_index INT;
  SET var_left_trim_index = 1;
  SET var_right_trim_index = 1;
  SET var_temp_l = '';
  SET var_temp_r = '';
  WHILE (CHAR_LENGTH(var_original) >= var_left_trim_index) DO
    SET var_temp_l = LEFT(var_original, var_left_trim_index);
    IF var_temp_l REGEXP var_pattern THEN
      WHILE (CHAR_LENGTH(var_temp_l) >= var_right_trim_index) DO
        SET var_temp_r = RIGHT(var_temp_l, var_right_trim_index);
        IF var_temp_r REGEXP var_pattern THEN
          RETURN var_temp_r;
          END IF;
        SET var_right_trim_index = var_right_trim_index + 1;
        END WHILE;
      END IF;
    SET var_left_trim_index = var_left_trim_index + 1;
    END WHILE;
  RETURN NULL;
END $$
DELIMITER ;

3

Bunu başarmanın kolay bir yolu olduğunu düşünüyorum ve benim için iyi çalışıyor.

REGEX kullanarak satırları SEÇME

SELECT * FROM `table_name` WHERE `column_name_to_find` REGEXP 'string-to-find'

REGEX kullanarak satırları GÜNCELLEME

UPDATE `table_name` SET column_name_to_find=REGEXP_REPLACE(column_name_to_find, 'string-to-find', 'string-to-replace') WHERE column_name_to_find REGEXP 'string-to-find'

REGEXP Referansı: https://www.geeksforgeeks.org/mysql-regular-expressions-regexp/


Teşekkür ederim :) Sürüm 8'den beri kolayca yapmak mümkündür.
Piskvor binadan ayrıldı
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.