Заглавные буквы в названиях городов, когда они начинаются с апострофа

#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 ? Все это выглядит немного странно и недостаточно проработано. Если дополнительно учесть, что исходное регулярное выражение уже было опубликовано здесь в качестве ответа, оно остается равным -1

2. Я согласен с тем, что 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, а не для специфичных для языка локализованных букв, таких как немецкие умляуты, символы с акцентом и т.д.