Отформатируйте строку, используя регулярное выражение в Java - PullRequest
13 голосов
/ 19 ноября 2011

Можно ли как-нибудь отформатировать строку в конкретный шаблон с помощью регулярных выражений, или более быстрый подход - сборщик строк + подстрока?

Например, введите номер телефона -> 1234567890 в качестве ввода

И получить вывод как -> (123) 456-7890

Я видел, что это возможно по этой статье: http://www.4guysfromrolla.com/webtech/031302-1.shtml, но данное объяснение есть в ASP. Как мне это сделать на Java ???

Ответы [ 6 ]

31 голосов
/ 20 ноября 2011

Отказ

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

Одно решение REGEX

Использование этого подходящего регулярного выражения (аналогично выражению Алана Мура ):

(.{3})(.{3})(.{4})

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

($1) $2-$3

производя замену, как вы просили. Конечно, он также будет соответствовать знакам препинания и буквам, что является причиной для использования \d (кодируется в строку Java как \\d), а не . подстановочный знак.

Почему РЕГЭКС?

Потенциальным преимуществом подхода регулярных выражений к чему-то подобному является сжатие «логики» для манипулирования строками. Поскольку вся «логика» может быть сжата в строку символов, а не в предварительно скомпилированный код, строки сопоставления и замены регулярных выражений могут быть сохранены в базе данных для облегчения манипулирования, обновления или настройки опытным пользователем системы. Это усложняет ситуацию на нескольких уровнях, но дает значительно большую гибкость для пользователей.

При других подходах (манипулирование строками) изменение алгоритма форматирования таким образом, чтобы он выдавал (555)123-4567 или 555.123.4567 вместо указанного вами (555) 123-4567, по сути, было бы невозможно просто через пользовательский интерфейс. с подходом регулярных выражений изменение будет таким же простым, как изменение ($1) $2-$3 (в базе данных или аналогичном хранилище) на $1.$2.$3 или ($1)$2-$3, в зависимости от ситуации.

Если вы хотите изменить свою систему так, чтобы она принимала «более грязные» данные, которые могут включать различные попытки форматирования, такие как 555-123.4567, и переформатировать их во что-то непротиворечивое, можно было бы создать алгоритм манипуляции со строками, который бы быть способным на это и перекомпилировать приложение, чтобы работать так, как вам хотелось бы. Однако с помощью регулярных выражений пересмотр системы не потребовался бы - просто измените выражения синтаксического анализа и замены, например, так (может быть, это немного сложно для начинающих понять сразу):

^\D*1?\D*([2-9])\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d).*$
($1$2$3) $4$5$6-$7$8$9$10

Это позволит значительно улучшить возможности программы, как показано в следующем переформатировании:

"Input"                       "Output"
----------------------------- --------------------------------
"1323-456-7890 540"           "(323) 456-7890"
"8648217634"                  "(864) 821-7634"
"453453453322"                "(453) 453-4533"
"@404-327-4532"               "(404) 327-4532"
"172830923423456"             "(728) 309-2342"
"jh345gjk26k65g3245"          "(345) 266-5324"
"jh3g24235h2g3j5h3"           "(324) 235-2353"
"12345678925x14"              "(234) 567-8925"
"+1 (322)485-9321"            "(322) 485-9321"
"804.555.1234"                "(804) 555-1234"
"08648217634"                 <no match or reformatting>

Как видите, он очень «терпим» к «форматированию» ввода и знает, что 1 следует игнорировать в начале числа и что 0 должно вызывать ошибку, поскольку оно недопустимо - все сохранено в одну строку.

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

TL; DR:

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

14 голосов
/ 20 ноября 2011

Один идет на RE, когда то же самое нельзя сделать с помощью substring или это труднее сделать.

В вашем случае лучше просто использовать StringBuilder и insert()

Предполагается, что проверка длины телефонного номера на месте (= 10 символов)

        String phoneNumber = "1234567890";
        StringBuilder sb = new StringBuilder(phoneNumber)
                                .insert(0,"(")
                                .insert(4,")")
                                .insert(8,"-");
        String output = sb.toString();
        System.out.println(output);          

выход

(123)456-7890
7 голосов
/ 20 ноября 2011

Та же техника работает на Java; вам просто нужно настроить синтаксис и API Java:

s = s.replaceFirst("(\\d{3})(\\d{3})(\\d{4})", "($1) $2-$3");

Я не понимаю, почему вы спрашиваете о более быстром подходе. Вы пробовали что-то подобное и испытывали проблемы с производительностью? Вы почти наверняка можете сделать это более эффективно с помощью StringBuilder, но в практическом плане это почти наверняка не стоит усилий.

Или вы говорили о времени, которое потребуется для изучения того, как выполнить это с помощью регулярного выражения относительно ручного кодирования с помощью StringBuilder? Хотя сейчас это своего рода спорный вопрос. : D

2 голосов
/ 19 ноября 2011

Я бы использовал комбинацию java String.format() метода и String.substring()

1 голос
/ 19 ноября 2011

Средство сопоставления регулярных выражений с группами - это на самом деле не что иное, как множество контейнеров String, а также много кода соответствия RE. (Вы можете посмотреть исходный код и убедиться в этом сами.) Это не дешевле, чем просто использовать substring(), особенно с фиксированным смещением, как в вашем случае.

0 голосов
/ 19 ноября 2011

StringBuilder с подстрокой будет быстрее, но не всегда самый простой / лучший подход.В этом случае я бы просто использовал подстроку.

String num = "1234567890";
String formatted = "(" + num.substring(0,3) + ") "
     + num.substring(3,6) + "-" + num.substring(6); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...