Разумное регулярное выражение для преобразования входной строки Whitespace-Comma-Whitespace в массив. Цитирование должно поддерживаться
Вот моя лучшая попытка (пока) решить эту проблему. Я новичок в регулярных выражениях, и эта проблема довольно существенная, но я попробую. RegEx явно освоить время.
Это, кажется, удовлетворяет требованиям разделителя / запятой. Мне это кажется излишним, хотя из-за повторного /s*
, Вероятно, есть лучший способ.
/\s*[,|\s*]\s*/
Я нашел это на SOF и пытаюсь разорвать его на части и применить к моей проблеме (не легко). Кажется, это удовлетворяет большинству требований "цитирования", но я все еще работаю над тем, как решить проблемы с разделителями в приведенных ниже требованиях.
/"(?:\\\\.|[^\\\\"])*"|\S+/
Требования, которые я пытаюсь удовлетворить:
- Будет использоваться функцией PHP preg_match_all() (или аналогичной) для разбиения строки на массив строк. Исходный язык - PHP.
- Слова во входной строке отделяются (0 или более пробелов) (необязательная запятая)(0 или более пробелов) или просто (1 или более пробелов).
- Входная строка также может иметь подстроки в кавычках, которые становятся единым элементом в выходном массиве.
- Подстроки в кавычках во входной строке должны сохранять свои двойные кавычки при размещении в выходном массиве (потому что мы должны быть в состоянии идентифицировать их позже, как они были изначально заключены в кавычки)
- Начальные и конечные пробелы (то есть пробелы между символом в двойных кавычках и самой строкой) в подстроках в кавычках должны быть удалены при помещении в выходной массив. Пример: "
hello world " становится "hello world" - Пробел внутри заключенных в кавычки фраз во входной строке должен быть уменьшен до одного пробела при размещении в элементе выходного массива. Пример: "Привет<пробел><вкладка><пробел><пространство>мир" становится "Привет<космос>мир"
- Подстроки во входной строке, которые имеют нулевую длину или содержат только пробелы, не помещаются в выходной массив (выходной массив не должен содержать элементов нулевой длины).
- Каждый элемент выходного массива должен быть обрезан (слева и справа) для пробелов.
Этот пример демонстрирует все требования выше:
Строка ввода:
"" один два три четыре пять шесть семь " " "
Возвращает этот массив (двойные кавычки фактически существуют в строках, показанных ниже):
{один два три четыре пять шесть семь"}
РЕДАКТИРОВАТЬ 13/13/2013
Я несколько дней усердно изучал регулярные выражения и, наконец, остановился на предложенном решении. Это может быть не лучшим, но это то, что у меня есть в это время.
Я буду использовать это регулярное выражение для разделения строки поиска на массив с помощью функции PHP preg_match_all ():
/(?:"([^"]*)"|([^\s",]+))/
Ведущий / завершающий "/" требуется функцией php preg_match_all().
Теперь, когда массив создан, мы извлекаем его из вызова функции следующим образом:
$x = preg_match_all(REGEX);
$Array = $x[0];
Мы должны сделать это, потому что функция возвращает составной массив, а элемент 0 содержит фактический вывод регулярного выражения. Другие возвращаемые элементы содержат значения, захваченные регулярным выражением, которые нам не нужны.
Теперь я буду повторять полученный массив и обрабатывать каждый элемент для удовлетворения требований (см. Выше), что будет намного проще, чем удовлетворение всех требований за один шаг с использованием одного регулярного выражения.
1 ответ
Я наконец-то разработал решение этой проблемы, которое включало несколько операторов PHP с использованием регулярных выражений. Ниже приведена последняя функция.
Эта функция является частью класса, поэтому она начинается с "public".
public function SearchString_ToArr($SearchString) {
/*
Purpose
Used to parse the specified search string into an array of search terms.
Search terms are delimited by <0 or more whitespace><optional comma><0 or more whitespace>
Parameters
SearchString (string) = The search string we're working with.
Return (array)
Returns an array using the following rules to parse the specified search string:
- Each search term from the search string is converted to a single element in the returned array.
- Search terms are delimited by whitespace and/or commas, or they may be double quoted.
- Double-quoted search terms may contain multiple words.
Unquoted Search Terms:
- These are delimited by any number of whitespace characters or commas in the search string.
- These have all leading and trailing whitespace trimmed.
Quoted Search Terms:
- These are surrounded by double-quotes in the search string.
- These retain leading and trailing double-quotes in the returned array.
- These have all leading and trailing whitespace trimmed.
- These may contain whitespace.
- These have all containing whitespace converted into a single space.
- If these are zero-length or contain only whitespace, they are not included in the returned array.
Example 1:
SearchString = ' "" one " two three " four "five six" " " '
Returns {"one", ""two three"", "four", ""five six""}
Notes The leading whitespace before the first "" is not returned.
The first quoted phrase ("") is empty so it is not returned.
The term "one" is returned with leading and trailing whitespace removed.
The phrase "two three" is returned with leading and trailing whitspace removed.
The phrase "two three" has containing whitespace converted to a single space.
The phrase "two three" has leading and trailing double-quotes retained.
...
Version History
1.0 2013.09.18 Tested by Russ Tanner on PHP 5.3.10.
*/
$r = array();
$Matches = array();
// Split the search string into an array based on whitespace, commas, and double-quoted phrases.
preg_match_all('/(?:"([^"]*)"|([^\s",]+))/', $SearchString, $Matches);
// At this point:
// 1. all quoted strings have their own element and begin/end with the quote character.
// 2. all non-quoted strings have their own element and are trimmed.
// 3. empty strings are omitted.
// Normalize quoted elements...
// Convert all internal whitespace to a single space.
$r = preg_replace('/\s\s+/', ' ', $Matches[0]);
// Remove all whitespace between the double-quotes and the string.
$r = preg_replace('/^"\s+/', '"', $r);
$r = preg_replace('/\s+"$/', '"', $r);
return $r;
}