Preg_replace, чтобы заглавная буква после цитаты

У меня есть такие имена:

$str = 'JAMES "JIMMY" SMITH'

Я запускаю strtolower, затем ucwords, который возвращает это:

$proper_str = 'James "jimmy" Smith'

Я хотел бы использовать вторую букву слов, в которой первая буква является двойной цитатой. Здесь регулярное выражение. Похоже, strtoupper не работает - regexp просто возвращает неизменное оригинальное выражение.

$proper_str = preg_replace('/"([a-z])/',strtoupper('$1'),$proper_str);

Любые подсказки? Спасибо!!

Ответ 1

Используйте e modifier, чтобы оценить подстановку:

preg_replace('/"[a-z]/e', 'strtoupper("$0")', $proper_str)

Где $0 содержит совпадение всего шаблона, поэтому " и строчная буква. Но это не имеет значения, поскольку " не изменяется при отправке через strtoupper.

Ответ 2

Вероятно, лучший способ сделать это - использовать preg_replace_callback():

$str = 'JAMES "JIMMY" SMITH';
echo preg_replace_callback('!\b[a-z]!', 'upper', strtolower($str));

function upper($matches) {
  return strtoupper($matches[0]);
}

Вы можете использовать флаг e (eval) на preg_replace() но я вообще советую против него. В частности, при работе с внешним входом это потенциально чрезвычайно опасно.

Ответ 3

Используйте preg_replace_callback Но вам не нужно добавлять дополнительную именованную функцию, а использовать анонимную функцию.

$str = 'JAMES "JIMMY" SMITH';
echo preg_replace_callback('/\b[a-z]/', function ($matches) {
     return strtoupper($matches[0]);
}, strtolower($str));

Использование /e устаревает с PHP 5.5 и не работает в PHP 7

Ответ 4

Что-то вроде этого может сделать трюк:

preg_replace("/(\w+)/e", "ucwords(strtolower('$1'))", $proper_str);

Ответ 5

Я делаю это без регулярного выражения, как часть моей пользовательской функции ucwords(). Предположим, что в строке появляется не более двух кавычек:

$parts = explode('"', $string, 3); 
if(isset($parts[2])) $string = $parts[0].'"'.ucfirst($parts[1]).'"'.ucfirst($parts[2]);            
else if(isset($parts[1])) $string = $parts[0].'"'.ucfirst($parts[1]);   

Ответ 6

Вы должны сделать это:

$proper_str = 
    preg_replace_callback(
        '/"([a-z])/',
        function($m){return strtoupper($m[1]);},
        $proper_str
);

Вы не должны использовать "eval()" по соображениям безопасности.

Во всяком случае, модификатор "e" патента устарел. См.: Документация по PHP.

Ответ 7

echo ucwords(mb_strtolower('JAMES "JIMMY" SMITH', 'UTF-8'), ' "'); // James "Jimmy" Smith

ucwords() имеет второй параметр разделителя, дополнительные разделители содержат символы разделителя слов. Используйте пробел '' и " в качестве разделителя, и "Jimmy" будет правильно распознан.

Ответ 8

Полное решение не упрощается/проще читать, чем это...

Код: https://3v4l.org/rrXP7

$str = 'JAMES "JIMMY" SMITH';
echo ucwords(strtolower($str), ' "');

Выход:

James "Jimmy" Smith

Это просто вопрос объявления двойных кавычек и пробелов как разделителей в ucwords().