Какое регулярное выражение будет использовать заглавные буквы после пробела? - PullRequest
5 голосов
/ 09 марта 2009

Я ищу регулярное выражение Perl, которое будет писать заглавными буквами любой символ, которому предшествует пробел (или первый символ в строке).

Я почти уверен, что есть простой способ сделать это, но у меня нет под рукой моей книги по Perl, и я делаю это недостаточно часто, чтобы запомнить ее ...

Ответы [ 7 ]

10 голосов
/ 09 марта 2009
s/(\s\w)/\U$1\E/g;

Я первоначально предложил:

s/\s\w/\U$&\E/g;

, но при использовании ' $ & ' сработали сигналы тревоги (даже до того, как я прочитал комментарий @ Манни) Оказывается, они полностью оправданы - использование операций $ &, $ `и $ 'приводит к общей неэффективности регулярных выражений.

\ E не является критическим для этого регулярного выражения; в этом случае отключается переключатель «установка регистра» \U или \L для строчных букв.


Как отмечено в комментариях, для соответствия первому символу строки необходимо:

s/((?:^|\s)\w)/\U$1\E/g;

Исправлено положение второй закрывающей скобки - спасибо, Blixtor.

8 голосов
/ 09 марта 2009

В зависимости от вашей конкретной задачи, это может быть сложнее, чем вы думаете, и простое регулярное выражение может не сработать. Вы думали о заглавных буквах в слове? Что если слово начинается с пунктуации, как «... Слово»? Есть ли исключения? А как насчет международных символов?

Возможно, лучше использовать модуль CPAN, например Text :: Autoformat или Text :: Capitalize , где эти проблемы уже решены.

use Text::Capitalize 0.2;
print capitalize_title($t), "\n";

use Text::Autoformat;
print autoformat{case => "highlight", right=>length($t)}, $t;

Звучит так, как будто Text :: Autoformat может быть более "стандартным", и я попробую это сначала. Его написал Дамиан . Но Text :: Capitalize делает несколько вещей, которые Text :: Autoformat не делает. Вот сравнение .

Вы также можете проверить Поваренная книга Perl для получателя 1.14 (стр. 31) о том, как использовать регулярные выражения для правильной заглавной буквы заголовка или заголовка.

7 голосов
/ 09 марта 2009

Нечто подобное должно сработать -

s!(^|\s)(\w)!$1\U$2!g

Это просто разбивает отсканированное выражение на два совпадения - $ 1 для пробела / начала строки и $ 2 для первого символа слова. Затем мы подставляем слова $ 1 и $ 2 после начала слова в верхнем регистре.

Я бы изменил \ s на \ b, что имеет больше смысла, так как здесь мы проверяем границы слов.

1 голос
/ 09 марта 2009

Если вы имеете в виду символ после пробела, используйте регулярные выражения, используя \s. Если вы действительно имеете в виду первый символ в слове, вы должны использовать \b вместо всех вышеперечисленных попыток с \s, что подвержено ошибкам.

s/\b(\w)/\U$1/g;
1 голос
/ 09 марта 2009

Обычно я не использую регулярное выражение, но мое решение не совсем то, что вы бы назвали "красивым":

$string = join("", map(ucfirst, split(/(\s+)/, $string)));

То, что split() s выводит строку через пробел и захватывает все пробелы, затем проходит через каждый элемент списка и делает ucfirst над ними (делая первый символ заглавными), затем join() возвращает их вместе одна строка. Не ужасно, но, возможно, вам больше понравится регулярное выражение. Лично мне просто не нравятся \Q или \U или другие полу-неловкие конструкции регулярных выражений.

РЕДАКТИРОВАТЬ: Кто-то еще упомянул, что пунктуация может быть потенциальной проблемой. Если, скажем, вы хотите это:

...string

изменено на это:

...String

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

$string = join("", map(ucfirst, split(/(\w+)/, $string)));

То же самое, но это split() s для слов (\w+), так что захваченные элементы списка доступны только для слов. Тот же общий эффект, но он будет использовать слова, начинающиеся с буквы. Измените \w на [a-zA-Z], чтобы избежать попыток использовать числа с большой буквы. И просто настраивайте его так, как вам нравится.

0 голосов
/ 18 марта 2009

Используйте заглавные буквы ЛЮБОЙ символ, которому предшествует пробел или начало строки:

s/(^|\s)./\u$1/g

Возможно, это очень неаккуратный способ сделать это, потому что теперь он также пропускает пробелы. :П Преимущество состоит в том, что он работает с буквами со всеми возможными акцентами (а также со специальными датскими / шведскими / норвежскими буквами), что проблематично, когда вы используете \ w и \ b в своем регулярном выражении. Можно ли ожидать, что все не-буквы не будут затронуты модификатором в верхнем регистре?

0 голосов
/ 09 марта 2009

Вы хотите сопоставить буквы за пробелом или в начале строки.

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

s/(?<=\s|^)(\w)/\u$1/g;    # this does not work!

Perl жалуется:

Variable length lookbehind not implemented in regex;

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

s/(?<!\S)(\w)/\u$1/g;

Более простой подход в этом конкретном случае, вероятно, состоит в том, чтобы просто соответствовать пробелу; тогда ограничение переменной длины снимается и включается в замену.

s/(\s|^)(\w)/$1\u$2/g;

Иногда вы не можете использовать этот подход в повторных подстановках, потому что то, что предшествует фактическому совпадению, уже съедено регулярным выражением, и хорошо иметь способ обойти это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...