Форматирование строки с использованием regex в Java

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

Например, укажите номер телефона → 1234567890 в качестве входа

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

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

Ответ 1

Один идет для 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

Ответ 2

Отказ

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

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

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

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

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

($1) $2-$3

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

Почему REGEX?

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

При использовании других подходов (манипуляции с строкой) изменение алгоритма форматирования так, чтобы оно создавало (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 позволяет хранить алгоритмы синтаксического анализа в относительно короткую строку, которая может быть легко сохранена для модификации без повторной компиляции. Более простые, более сфокусированные функции манипулирования строкой более эффективны и иногда могут выполнять больше, чем регулярное выражение. Ключ должен понимать как инструменты, так и требования приложения и использовать наиболее подходящий для ситуации.

Ответ 3

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

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

String num = "1234567890";
String formatted = "(" + num.substring(0,3) + ") "
     + num.substring(3,6) + "-" + num.substring(6);