Функція повернення лише рядково-цифрових символів із рядка?


98

Я шукаю функцію php, яка прийме вхідний рядок і поверне дезінфіковану версію, видаляючи всі спеціальні символи, залишаючи лише буквено-цифрові.

Мені потрібна друга функція, яка робить те саме, але повертає лише алфавітні символи AZ.

Будь-яка допомога дуже цінується.


У якій формі для нормалізації Unicode це, і чому б ви хотіли це зробити?
christ

1
Коли ви говорите AZ та «буквено-цифрові», ви насправді маєте на увазі лише AZ або ви хочете збігати всі літери з усіх мов, включаючи іноземні мови та застарілі сценарії?
Марк Байерс

Якщо ви робите це, щоб зробити порівняння рядків, нечутливих до наголосів, ви робите неправильно.
trist

3
Це не просто "з усіх мов". Це англійська. Англійською мовою використовується латинська писемність. Існує unichars '\p{Latin}' '\p{Alphabetic}' '[^A-Za-z]' | wc -l== 1192 кодових точок, які є латинськими алфавітами, але не є AZ. Поширений міф, що ASCII достатньо для англійської мови. Це не так, і тому написання AZ має запах коду .
christ

1
@Scott B: Англійська мова не просто використовує 26 листів від AZ. Наприклад, слово резюме включає é. Можливо, ви могли б пояснити, що ви намагаєтесь зробити, оскільки це може допомогти вам отримати кращі відповіді.
Марк Байерс

Відповіді:


212

Попередження: Зверніть увагу, що англійська мова не обмежується лише AZ.

Спробуйте це, щоб видалити все, крім az, AZ та 0-9:

$result = preg_replace("/[^a-zA-Z0-9]+/", "", $s);

Якщо ваше буквено-цифрове визначення включає літери іноземними мовами та застарілі скрипти, тоді вам потрібно буде використовувати класи символів Unicode.

Спробуйте це, щоб залишити лише AZ:

$result = preg_replace("/[^A-Z]+/", "", $s);

Причиною попередження є те, що такі слова, як резюме, містять букву, éяка не відповідає цьому. Якщо ви хочете відповідати певному списку літер, відрегулюйте регулярний вираз, щоб включити ці літери. Якщо ви хочете зрівняти всі літери, використовуйте відповідні класи символів, як зазначено в коментарях.


2
Ні, буквено-цифрове це [\p{Alphabetic}\p{Numeric}]. Я забув властивість алфавіту PCRE, але ви можете наблизити його до [\pL\pM\pN].
trist

1
@tchrist: Я припускаю, що, оскільки він спеціально згадав AZ, він хоче лише відповідати цьому, хоча я визнаю, що питання може бути набагато більш зрозумілим з цього приводу. Я попрошу пояснити.
Mark Byers

1
@Mark, я не сперечався з другою частиною вашої відповіді, хоча якщо він не канонічно розклав рядок першим, це не спрацює правильно. Я сперечався з першою частиною. Крім того, я намагаюся завжди виправляти регулярні вирази, які працюють на будь-яких даних, а не лише на запліснявілих старих ASCII. :) Звідси мантра, що ця сторона Тисячоліття [A-Z], іноді завжди помилкова .
trist

1
@ Марк Байерс, я бачу .. і так, я віддаю перевагу, iале мені доводиться лише хвилюватись щодо англійської демографічної групи. Я забуваю, що багато людей повинні думати про інші мови. До речі, я щойно помітив, що ви найпопулярніший користувач, який ніколи не задавав 1 запитання. Навіть Джон Скіт раніше задавав питання!
JD Isaacks 04.03.11

1
чому в кінці регулярного виразу є знак +? Чи не буде ... так само, якби ви його видалили?
Денніс,

2

Замість того preg_replace, ви завжди можете використовувати функції фільтрації PHP, використовуючи filter_var()функцію з FILTER_SANITIZE_STRING.


Чи має PHP доступ до алгоритму ISO Stringprep? Я знаю, що Perl і Java це роблять.
trist

Я вважаю, що функція рядкового фільтра працює переважно з 7-бітовим ASCII, але не цитуйте мене з цього приводу.
Марк Бейкер,

30
Будь ласка, чи можете ви сказати нам чіткий спосіб зробити те, що користувач просить використовувати FILTER_SANITIZE_STRING? Наскільки мені відомо, найближче, що можна досягти таким чином, - це FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH, але це не залишає лише букв і цифр, а також крапки, скісні риски, відсотки і все це.
Пере

$ iMycleanVar = filter_var ($ sStringWithNumbers, FILTER_SANITIZE_NUMBER_INT);
Султанос

4
Це більше схоже на коментар, а не на відповідь. Дайте належне пояснення, пишучи відповідь.
Siraj Alam

0
  1. Протріть число [ 0-9 ] та алфавіти загалом [ \ pL ]:
$string = preg_replace("/[^0-9\pL]+/", "", $string)
  1. Протруйте спеціально для алфавітів від A до Z (не враховуючи регістр) [ a-zA-Z ]:
$string = preg_replace("/[^a-zA-Z]+/", "", $string)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.