Замена символа ’ в PHP

Мне трудно заменить этот странный правильный символ одинарной кавычки. Я использую str_replace следующим образом:

str_replace("’", '\u1234', $string);

Похоже, я не могу понять, какой персонаж на самом деле является цитатой. Даже когда я копирую и вставляю его прямо из PHPMyAdmin, он все равно не работает. Должен ли я как-то избежать этого?

Персонаж: http://www.lukomon.com/Afbeelding%204.png

  • Кодировка MySQL: Юникод UTF-8 (utf8)
  • Сопоставления MySQL: utf8_unicode_ci
  • <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

EDIT: это оказалась одинарная кавычка Microsoft, которую я мог заменить на эта функция из комментария Фила Паффорда. Не уверен, какой ответ я должен отметить сейчас ..


person richard    schedule 29.04.2010    source источник
comment
Почему вы хотите избежать этого? Как это мешает чему-либо?   -  person zneak    schedule 30.04.2010
comment
Скорее всего, если ведет себя не так, как вы хотите, вы нарушите все символы, отличные от ASCII. Пришло время проверить один из 2 000 000 вопросов SO о том, «почему Unicode не проходит через мой PHP?». (Обычно из-за отсутствия UTF-8, mysql_set_charset или использования htmlentities вместо правильного htmlspecialchars.)   -  person bobince    schedule 30.04.2010
comment
Ошибся там. Мне нужно заменить его, а не сбежать. Я использую htmlspecialchars, но пытался заменить символ до htmlspecialchars и после него. Нет эффекта. mysql_set_charset - это неопределенная функция, хотя база данных находится в utf8.   -  person richard    schedule 30.04.2010
comment
Просто чтобы проверить, вы беспокоитесь о ', а не о `, верно? (апостроф — по клавише ввода, а обратная кавычка — над клавишей табуляции)   -  person jcolebrand    schedule 03.05.2010
comment
Это не обычная цитата и не обратная кавычка.   -  person richard    schedule 04.05.2010
comment
stackoverflow.com/ вопросы/1262038/ могут помочь   -  person Phill Pafford    schedule 05.05.2010
comment
iconv() здесь должно работать, не так ли?   -  person Frank Farmer    schedule 08.05.2010
comment
@richard FWIW, мой ответ предлагает найти символ Юникода в кодовой точке 2019. В Windows-1252 этот символ кодируется как 92 (шестнадцатеричный) или 146 (десятичный), что по сути совпадает с решением Фила. Только замена кодовой точкой Unicode более гибкая между кодировками.   -  person Peter Bailey    schedule 08.05.2010
comment
@richard - Вы должны отметить ответ, получивший наибольшее количество голосов (поскольку это то, что система будет делать в любом случае, за исключением того, что они просто получат меньше баллов)   -  person Mitch Dempsey    schedule 09.05.2010


Ответы (10)


Это случилось и со мной. Пара вещей:

  • Используйте функцию htmlentities для вашего текста

    $my_text = htmlentities($string, ENT_QUOTES, 'UTF-8');

Подробнее о функции htmlentities.

  • Используйте правильный тип документа, это помогло мне.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  • Используйте тип кодировки utf-8 на своей странице:

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Вот окончательный прототип вашей страницы:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>    
<body>

<?php     
    // your code related to database        
    $my_text = htmlentities($string, ENT_QUOTES, 'UTF-8');    
?>

</body>
</html>

.

Однако, если вы хотите заменить его, попробуйте mb_ereg_replace функция.

Пример:

mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");

$my_text = mb_ereg_replace("’","'", $string);
person Sarfraz    schedule 02.05.2010
comment
Спасибо за Ваш ответ. На самом деле мне действительно не хватало doctype или любого другого HTML. Как только я добавил его, и ваше правило htmlentities стало . Как только я переключил Firefox на западную кодировку ISO, она снова изменилась на . str_replace по-прежнему не работает, и, к сожалению, mb_ereg_replace тоже не работает. - person richard; 02.05.2010
comment
Попробуйте это: str_replace("’", "'", $string);, а также попробуйте удалить функцию htmlentites, а затем посмотрите. - person Sarfraz; 02.05.2010
comment
С функцией сущностей html вся запись просто исчезает. Если я удаляю функцию, она показывает . Моя база данных - UTF-8, но я могу изменить ее в PHPMyAdmin? - person richard; 02.05.2010
comment
@richard: да, вы можете изменить кодировку в phpmyadmin, есть опция после выбора базы данных. - person Sarfraz; 02.05.2010
comment
@Sarfraz: на что мне его изменить? Я попытался установить его на utf8_unicode_ci, но это ничего не изменило в выводе. Спасибо. - person richard; 03.05.2010
comment
@richard: для него должно быть установлено значение utf8_unicode_ci, чтобы разрешить иностранные языки, но вы не уверены, к какой кодировке принадлежит этот символ. Возможно, вы также захотите попробовать любую из кодировок latin. - person Sarfraz; 03.05.2010

У меня была такая же проблема, и я нашел, что это работает:

function replace_rsquote($haystack,$replacewith){
   $pos = strpos($haystack,chr("226"));
   if($pos > -1){
       return substr_replace($haystack,$replacewith,$pos,3);
   } else return $haystack;
}

Пример:

echo replace_rsquote("Nick’s","'"); //Nick's
person David Kinkead    schedule 05.10.2012

Чтобы узнать, что это за символ, запустите его через функцию ord, которая даст вам ASCII-код символа:

echo ord('’'); // 226

Теперь, когда вы знаете, что это такое, вы можете сделать это:

str_replace('’', chr(226), $string);
person Casey Chu    schedule 02.05.2010
comment
Это просто заменяет персонажа копией самого себя. - person kingjeffrey; 08.05.2010
comment
Хороший вопрос, но исходный код плаката делает то же самое, поэтому я решил сделать то же самое. - person Casey Chu; 08.05.2010

Если вы используете символы, отличные от ASCII, в своем PHP-коде, вам необходимо убедиться, что вы используете ту же кодировку символов, что и в обрабатываемых данных. Ваша попытка, вероятно, не удалась, потому что вы используете другую кодировку символов в своем PHP-скрипте, чем в $string.

Кроме того, если вы используете многобайтовую кодировку символов, такую ​​как UTF-8, вам также следует использовать многобайтовые строковые функции.

person Gumbo    schedule 02.05.2010

Чтобы заменить его:

Если ваш файл сценария закодирован в той же кодировке, что и данные, в которых вы пытаетесь выполнить замену, он должен работать так, как вы его опубликовали. Если вы работаете с данными UTF-8, убедитесь, что скрипт закодирован в UTF-8, а ваш редактор не транслитерирует символ без вывода сообщений при вставке.

Если это не сработает, попробуйте экранировать его, как описано ниже, и посмотрите, какой код он возвращает.

Чтобы избежать этого:

Если ваш исходный файл закодирован в UTF-8, это должно работать:

$string = htmlentities($string, ENT_QUOTES, "UTF-8");

набор символов по умолчанию для html...iso-8859-1. Все, что отличается от этого, должно быть указано явно.

Для более сложных проблем с преобразованием символов всегда обращайтесь к примечаниям пользователей к таким функциям, как htmlentities(). там можно найти настоящие жемчужины.

В целом:

Бобинс прав в своем комментарии, проблемы с системными наборами символов следует сортировать систематически, чтобы они не кусали вас за задницу - хотя бы путем определения того, какой набор символов используется на каждом этапе пути:

  • Как закодирован файл скрипта;
  • Как подается документ;
  • Как данные хранятся в базе данных;
  • Как кодируется соединение с базой данных.
person Pekka    schedule 02.05.2010
comment
Файл сохранен в кодировке UTF-8. Метатег HTML — UTF-8. База данных UTF-8. Подключение к базе данных... Вызов неопределенной функции. К сожалению, я считаю, что это может быть проблемой. - person richard; 02.05.2010

Гамбо, грустно, верно -
- сохраните скрипт как файл utf-8
- и используйте http://php.net/mbstring (как указал Сарфраз в своем последнем примере)

person arena-ru    schedule 04.05.2010

Почему бы не запустить строку через htmlspecialchars() и не вывести ее, чтобы увидеть, во что она превращает этот символ, чтобы вы знали, что использовать в качестве выражения замены?

person user97410    schedule 29.04.2010
comment
Я пробовал это, но ничего не происходит. Запятая осталась как есть :( - person richard; 30.04.2010

Этот символ у вас есть правая одинарная кавычка.

Чтобы заменить его шаблоном, вам нужно сделать что-то вроде этого

$string = preg_replace( "/\\x{2019}/u", 'replacement', $string );

Но на самом деле это касается только симптома. Проблема в том, что у вас нет последовательного использования кодировок символов во всем приложении, как отмечали другие.

person Peter Bailey    schedule 03.05.2010
comment
С вашим шаблоном замены строка, содержащая правую одиночную кавычку, возвращается пустой. Я бы не знал, что изменить сейчас. Кодировка MySQL — UTF-8, словосочетание utf8_unicode_ci и метатег html utf-8. - person richard; 04.05.2010
comment
Я не совсем уверен, что вы подразумеваете под пустым возвратом. Можете ли вы быть более явным? - person Peter Bailey; 04.05.2010
comment
Я запрашиваю 12 строк, 1 строка содержит эту запятую. PHP с этим выражением замены возвращает 11 строк. - person richard; 05.05.2010
comment
PHP не возвращает строки. SQL-сервер делает. И даже тогда preg_replace() работает с одной строкой — возможно, со столбцом, а не со строкой. Вы все еще путаете меня. Вы пытались переместить это регулярное выражение в SQL-запрос? - person Peter Bailey; 05.05.2010
comment
preg_replace — это тяжелая функция для статического символа — без необходимости сложного сопоставления шаблонов регулярных выражений нет причин для сравнительно медленной preg_replace. str_replace будет намного быстрее. - person kingjeffrey; 08.05.2010
comment
@kingjeffrey - это полностью микрооптимизация. Точный? Иногда (preg_replace может быть быстрее неожиданным образом). Соответствующие? Нет, я так не думаю. - person Peter Bailey; 08.05.2010
comment
@Peter Bailey, это полностью микрооптимизация ... str_replace () выполняет преформы на 50% быстрее, чем preg_replace () для простой замены строки. Я собрал этот тест вместе: test.kingdesk.com/preg-replace-v -str-заменить. Для сложных приложений (таких как плагин wp-Typography: wordpress.org/extend/plugins/wp -typography), это может сэкономить секунды на сложных операциях синтаксического анализа. - person kingjeffrey; 09.05.2010

Не используйте функции регулярных выражений ( preg_replace или mb_ereg_replace ). Они слишком тяжелые для этого.

str_replace(chr(226),'\u2019' , $string);

Если ваша игла представляет собой многобайтовый символ, возможно, вам повезет больше с этой специальной функцией:

<?php 
function mb_str_replace($needle, $replacement, $haystack) {
    $needle_len = mb_strlen($needle);
    $replacement_len = mb_strlen($replacement);
    $pos = mb_strpos($haystack, $needle);
    while ($pos !== false)
    {
        $haystack = mb_substr($haystack, 0, $pos) . $replacement
                . mb_substr($haystack, $pos + $needle_len);
        $pos = mb_strpos($haystack, $needle, $pos + $replacement_len);
    }
    return $haystack; 
} 
?>

кредит для этой последней функции: http://www.php.net/manual/en/ref.mbstring.php#86120

person kingjeffrey    schedule 08.05.2010

Вы можете получить код char ascii с помощью ord, а затем заменить его нужным символом:

$asciicode = ord('’'); // 146
$stringfixed = str_replace(chr($asciicode), '\'', $string);
person Emanuel A.    schedule 31.07.2017