#php #regex
#php #регулярное выражение
Вопрос:
У меня проблема с правильной заглавной буквой названий городов (голландских), когда они начинаются с апострофа. Например, у меня могли бы быть имена:
‘S-ХЕРТОГЕНБОС, или ‘s gravendeel, или ‘T Harde
Что я хотел бы сделать, так это перевести все в нижний регистр, а затем заглавными буквами следующую букву после префикса ‘S или ‘s или ‘T. Таким образом, результат должен быть:
Хертогенбос, Гравендил и т Харди
Я подумываю об использовании регулярного выражения для этого, но пока не совсем уверен, как это следует делать. Может ли кто-нибудь указать мне правильное направление?
Спасибо!
Комментарии:
1. вам нужно заменить названия городов в тексте или вы можете передать только название города в функции?
2. Привет, Мерлин, я могу передать название города функции.
Ответ №1:
Вы могли бы использовать preg_replace_callback
.
$city = strtolower("'T-HERTOGENBOSCH");
echo preg_replace_callback("/('(s|t)( |-))([a-z])/", function($matches) {
return $matches[1] . ucfirst($matches[4]);
}, $city);
Шаблон использует несколько подшаблонов, результаты которых повторно собираются в функции обратного вызова:
('(s|t)( |-)) # Apostrophe, then 's' or 't', then '<space>' or '-'
([a-z]) # The following lowercased character
Обратите внимание, что я заключил первую часть в дополнительный подшаблон. Это упрощает повторную сборку.
Ответ №2:
Попробуйте следующую функцию, основанную на регулярном выражении sanchises (я его немного отредактировал …):
function dutch_city_name($name) {
$name = strtolower(trim($name));
$matches = array();
preg_match("/'([a-z])( |-)[a-z]*/", $name, $matches);
if(count($matches) == 0) {
return $name;
}
return "'".$matches[1].$matches[2].ucfirst(substr($name, 3, strlen($name) - 3));
}
Я попробовал это, и это работает.
Комментарии:
1. Почему вы сначала
strtolower
, а затем сопоставляетеA-Z
(дважды)? Почему вы объявили$match
? Все это выглядит немного странно и недостаточно проработано. Если дополнительно учесть, что исходное регулярное выражение уже было опубликовано здесь в качестве ответа, оно остается равным -12. Я согласен с тем, что strtolower и A-Z, но почему я не должен заранее объявлять $ match? Наверное, мне это и не нужно, но мне все равно нравится это писать. Это вопрос личного стиля кодирования… Эта функция решает проблему, возможно, это не лучшее решение, но это не соревнование в кодировании…
3. Позже вы использовали
$matches
не$match
.. В этом нет ничего особенного, просто опечатка. Как я уже сказал, это просто одна из проблем. Основная проблема заключается в том, чтоpreg_match()
здесь не является подходящим инструментом и, кроме того, используется не очень эффективно4. Ок, да, это опечатка, спасибо, что указали на это. Я исправлю это.
Ответ №3:
Во-первых, я хотел бы порекомендовать такие сайты, как regex101.com или эквивалент. Затем давайте обсудим с вами очень простое регулярное выражение: -Вы хотите, чтобы за буквальным символом «‘» следовал ровно один другой символ, который вы хотели бы сопоставить с «некапитализировать», — а затем целое слово
В принципе, вам нужно сопоставить что-то в форме '(a-zA-Z)(?: |-)[a-zA-Z]*
. Слева направо
- ‘ Буквальный
'
(a-zA-Z)
Один символ в алфавите, в нижнем или верхнем регистре. Является соответствующей группой.(?: |-)
Либо пробел, либо тире. Не является подходящей группой[a-zA-Z]*
Последовательность символов в алфавите. Может быть(a-zA-Z)*
, если вы тоже хотите что-то с этим битом.
Теперь, когда у вас есть соответствие, все, что вам нужно сделать, это заменить его на некапитализированную версию, например, с помощью функции PHP.
Комментарии:
1. Большое вам спасибо за четкое объяснение и ссылку! Я принял ответ Мерлина, который является образцом рабочего кода, основанным на вашем объяснении.
Ответ №4:
Вот одно из них без регулярного выражения. Он просто проверяет, является ли первый символ апострофом, и если да, пропускает символ после апострофа при поиске первой буквы с заглавной буквы.
function capitalizeCityName($name) {
$name = strtolower(trim($name));
$i = ($name[0] === "'") ? 2 : 1;
for(; $i<strlen($name); $i ) {
if(ctype_alpha($name[$i])) {
$name[$i] = strtoupper($name[$i]);
break;
}
}
return $name;
}
print capitalizeCityName("'T Harde"); //'t Harde
print capitalizeCityName("Harde"); //Harde
Ответ №5:
Я не знаю, поддерживает ли функция PHP replace, которую вы хотите использовать, изменение регистра букв в строке динамической замены. Но следующее работало с механизмом регулярных выражений Perl в текстовом редакторе UltraEdit версии 21.10.
Строка поиска:
'([STst])(W)(w)([w-] )
Заменить строку:
'L1E2U3EL4E
или
'l12u3L4E
Строка поиска соответствует:
- прямой апостроф,
- за которым следует символ
s
илиt
в любом случае, помеченный для обратной ссылки как строка 1, - один символ, не являющийся словом, помеченный для обратной ссылки как строка 2,
- символ одного слова, помеченный для обратной ссылки как строка 3,
- 1 или более дополнительных символов слова или дефисов, помеченных для обратной ссылки как строка 4.
Строка замены:
- сохраняет апостроф,
- первая выделенная строка (символ
s
илиt
в любом случае), преобразованная в нижний регистр, - вторая помеченная строка без изменений,
- третья выделенная строка (символ первого слова названия города) преобразуется в верхний регистр,
- четвертая выделенная строка преобразована в нижний регистр.
Объяснение специальных символов в строке замены:
l
… преобразуйте только следующий символ в нижний регистр.u
… преобразуйте только следующий символ в верхний регистр.L
… преобразуйте все символы с точностью доE
в нижний регистр.U
… преобразуйте все символы с точностью доE
в верхний регистр.
Примечание: Преобразование регистра работает только для букв ASCII A-Za-z, а не для специфичных для языка локализованных букв, таких как немецкие умляуты, символы с акцентом и т.д.