Как разделить созданную пользователем строку, которая может содержать разделитель? - PullRequest
1 голос
/ 19 сентября 2009

Я бы хотел String.Split () следующую строку, используя запятую в качестве разделителя:

John,Smith,123 Main Street,212-555-1212

Вышеуказанный контент вводится пользователем. Если они введут запятую в своем адресе, результирующая строка вызовет проблемы с String.Split (), поскольку теперь у вас есть 5 полей вместо 4:

John,Smith,123 Main Street, Apt 101,212-555-1212

Я могу использовать String.Replace () для всех пользовательских данных, чтобы заменить запятые чем-то другим, а затем снова использовать String.Replace (), чтобы преобразовать вещи обратно в запятые:

value = value.Replace(",", "*");  

Однако это все равно можно обмануть, если пользователь использует разделитель «*» в своих входных данных. Тогда вы получите лишние запятые и без звездочек в результате.

Я вижу в Интернете решения для работы с экранированными разделителями, но я не нашел решения для этой, казалось бы, распространенной ситуации. Чего мне не хватает?

РЕДАКТИРОВАТЬ: Это называется столкновения разделителя .

Ответы [ 9 ]

4 голосов
/ 20 сентября 2009

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

У вас есть несколько вариантов:

  1. Ограничение ввода : Если это приемлемо для вашего сценария, самое простое решение - ограничить использование разделителей в значениях. В вашем конкретном случае это означает запрещение запятых.
  2. Кодировка : если ограничение ввода не подходит, следующим самым простым вариантом будет кодирование всего входного значения. Выберите кодировку, которая не имеет разделителей в своем диапазоне возможных выходных данных (например, Base64 не содержит запятых в своем кодированном выходном сигнале)
  3. Экранирование разделителей : Несколько более сложный вариант заключается в создании соглашения об экранировании разделителей. Если вы работаете с чем-то вроде мейнстрима, таким как CSV, вполне вероятно, что проблема побега уже решена, и вы можете использовать стандартную библиотеку. Если нет, то нужно подумать над тем, чтобы придумать полную экранирующую систему и внедрить ее.

Если у вас есть возможность не использовать CSV для представления данных, это откроет множество других возможностей. (Например, рассмотрим способ, которым параметризованные SQL-запросы обходят сложность экранирования ввода, сохраняя значения параметров отдельно от строки запроса.)

3 голосов
/ 19 сентября 2009

Если это CSV , адрес должен быть заключен в кавычки. Широко доступны парсеры CSV, которые учитывают это при разборе текста.

John,Smith,"123 Main Street, Apt. 6",212-555-1212
3 голосов
/ 19 сентября 2009

Это может быть не вариант для вас, но не будет ли проще использовать очень необычный символ, скажем, трубу |, в качестве разделителя и не разрешать ввод этого символа в первом случае?

2 голосов
/ 19 сентября 2009

Одним из надежных решений было бы преобразование ввода пользователя в base64, а затем через запятую. Это будет означать, что вам придется конвертировать обратно после разбора.

0 голосов
/ 20 сентября 2009

В некотором смысле, пользователь уже"экранирует" запятую с пробелом позже.

Итак, попробуйте это:

string[] values = RegEx.Split(value, ",(?![ ])");

Пользователь по-прежнему может нарушить это, если он не поставит пробел, и есть более надежный метод (использующий стандартный метод CSV для цитирования значений, которые содержат запятые), но это поможет вам в случае использования представили.

Еще одно решение: предоставьте поле «Адрес 2», в которое традиционно помещаются такие вещи, как номера квартир. Пользователь все еще может сломать его, если он ленив, хотя то, что он на самом деле нарушит поля после address2.

0 голосов
/ 19 сентября 2009

Забавное решение (работает, если адрес - единственное поле с комой):

Разбить строку по коме. Первые две части будут имя и фамилия; последняя часть - телефон - забери их. Комбинируй остальное в коме обратно - это будет адрес;)

0 голосов
/ 19 сентября 2009

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

0 голосов
/ 19 сентября 2009

Вежливо напомните своим пользователям, что правильно сформированные адреса в Соединенных Штатах и ​​Канаде НИКОГДА не должны содержать знаков препинания, возможно?

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

Даже USPS требует, чтобы пользователь выполнил большую часть работы, введя компоненты адреса в отдельные поля на странице их адреса "canonicalizer" (http://zip4.usps.com/zip4/welcome.jsp).

0 голосов
/ 19 сентября 2009

Вы можете попытаться поместить кавычки или некоторые другие начальный и конечный разделители вокруг каждого пользовательского ввода и игнорировать любой специальный символ между набором кавычек.

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

Лучшее решение - определить допустимые символы и как-то отклонить недопустимые символы, а затем использовать недопустимый символ (который не будет отображаться во входных данных, поскольку они «запрещены») в качестве разделителей

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