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

Я новичок в регулярных выражениях и буду благодарен вам за помощь. Я пытаюсь собрать выражение, которое разделит строку примера, используя все пробелы, которые не окружены одинарными или двойными кавычками. Моя последняя попытка выглядит так: (?!") И не совсем работает. Она разбивается на пробел перед цитатой.

Пример ввода:

 This is a string that "will be" highlighted when your 'regular expression' matches something. 

Желаемый результат:

 This is a string that will be highlighted when your regular expression matches something. 

Обратите внимание, что "will be" и 'regular expression' сохраняют пробел между словами.

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

 [^\s"']+|"([^"]*)"|'([^']*)' 

Я добавил группы захвата, потому что вам не нужны кавычки в списке.

Этот Java-код создает список, добавляя группу захвата, если он соответствует, чтобы исключить кавычки, и добавление общего соответствия регулярному выражению, если группа захвата не совпала (сопоставлено несогласованное слово).

 List matchList = new ArrayList(); Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"); Matcher regexMatcher = regex.matcher(subjectString); while (regexMatcher.find()) { if (regexMatcher.group(1) != null) { // Add double-quoted string without the quotes matchList.add(regexMatcher.group(1)); } else if (regexMatcher.group(2) != null) { // Add single-quoted string without the quotes matchList.add(regexMatcher.group(2)); } else { // Add unquoted word matchList.add(regexMatcher.group()); } } 

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

 List matchList = new ArrayList(); Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'"); Matcher regexMatcher = regex.matcher(subjectString); while (regexMatcher.find()) { matchList.add(regexMatcher.group()); } 

В StackOverflow есть несколько вопросов, которые охватывают этот же вопрос в различных контекстах с использованием регулярных выражений. Например:

  • строки синтаксического анализа: извлечение слов и фраз
  • Лучший способ parsingа пространственно разделенного текста

UPDATE : примерное регулярное выражение для обработки одиночных и двойных кавычек. Ссылка: Как я могу разделить на строку, кроме как внутри кавычек?

 m/('.*?'|".*?"|\S+)/g 

Протестировали это быстрым fragmentом Perl, и результат был воспроизведен ниже. Также работает для пустых строк или строк только в виде пробелов, если они находятся между кавычками (не уверен, что это желательно или нет).

 This is a string that "will be" highlighted when your 'regular expression' matches something. 

Обратите внимание, что это включает сами символы кавычек в согласованных значениях, хотя вы можете удалить это с заменой строки или изменить регулярное выражение, чтобы не включать их. Я оставлю это как упражнение для читателя или другого плаката на данный момент, так как 2am слишком поздно, чтобы больше возиться с регулярными выражениями;)

Если вы хотите разрешить скрытые кавычки внутри строки, вы можете использовать что-то вроде этого:

 (?:(['"])(.*?)(?\\\\)*\1|([^\s]+)) 

Цитированными строками будут группы 2, одиночные некотируемые слова будут группой 3.

Вы можете попробовать его на разных строках здесь: http://www.fileformat.info/tool/regex.htm или http://gskinner.com/RegExr/

Регулярное выражение из Jan Goyvaerts – лучшее решение, которое я нашел до сих пор, но создает также пустые (нулевые) совпадения, которые он исключает в своей программе. Эти пустые совпадения также отображаются в тестерах regex (например, rubular.com). Если вы включите поиск arround (сначала найдите цитированные части и слова, разделенные пробелами), вы можете сделать это один раз с помощью:

 ("[^"]*"|'[^']*'|[\S]+)+ 
 (? 

Это будет соответствовать пробелам, не окруженным двойными кавычками. Я должен использовать min, max {0,99999}, потому что Java не поддерживает * и + в lookbehind.

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

Разум, вы можете разделить его на пространства до и после "will be" . Но я не могу придумать, как можно указать игнорирование пространства между разделом.

(не фактическая Java)

 string = "This is a string that \"will be\" highlighted when your 'regular expression' matches something."; regex = "\"(\\\"|(?!\\\").)+\"|[^ ]+"; // search for a quoted or non-spaced group final = new Array(); while (string.length > 0) { string = string.trim(); if (Regex(regex).test(string)) { final.push(Regex(regex).match(string)[0]); string = string.replace(regex, ""); // progress to next "word" } } 

Кроме того, захват одиночных кавычек может привести к проблемам:

 "Foo's Bar 'n Grill" //=> "Foo" "s Bar " "n" "Grill" 

String.split() здесь не помогает, потому что нет возможности различать пробелы внутри кавычек (не разделять) и внешние (разделенные). Matcher.lookingAt() , вероятно, вам нужно:

 String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something."; str = str + " "; // add trailing space int len = str.length(); Matcher m = Pattern.compile("((\"[^\"]+?\")|('[^']+?')|([^\\s]+?))\\s++").matcher(str); for (int i = 0; i < len; i++) { m.region(i, len); if (m.lookingAt()) { String s = m.group(1); if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'"))) { s = s.substring(1, s.length() - 1); } System.out.println(i + ": \"" + s + "\""); i += (m.group(0).length() - 1); } } 

который производит следующий вывод:

 0: "This" 5: "is" 8: "a" 10: "string" 17: "that" 22: "will be" 32: "highlighted" 44: "when" 49: "your" 54: "regular expression" 75: "matches" 83: "something." 

Мне понравился подход Маркуса, однако я изменил его так, чтобы я мог разрешить текст рядом с кавычками и поддерживать оба символа «и». Например, мне нужно было a = «некоторое значение», чтобы не разделить его на [a = некоторая ценность “].

 (? 

Пару надеемся, полезные настройки на принятый ответ Яна:

 (['"])((?:\\\1|.)+?)\1|([^\s"']+) 
  • Позволяет избегать кавычек в цитированных строках
  • Избегает повторения шаблона для одиночной и двойной кавычек; это также упрощает добавление дополнительных котировочных символов, если необходимо (за счет еще одной группы захвата)

Подход Яна велик, но вот еще один для записи.

Если вы действительно хотели разделить, как указано в названии, сохраняя кавычки в "will be" и 'regular expression' , вы можете использовать этот метод, который прямо из шаблона соответствия (или замены), за исключением ситуаций s1, s2 , s3 и т. д.

Регулярное выражение:

 '[^']*'|\"[^\"]*\"|( ) 

Два левых чередования соответствуют полным 'quoted strings' и "double-quoted strings" . Мы проигнорируем эти матчи. Правая сторона сопоставляет и фиксирует пробелы в группе 1, и мы знаем, что они являются правильными пространствами, потому что они не соответствовали выражениям слева. Мы заменим их SplitHere затем SplitHere на SplitHere . Опять же, это для истинного раздельного случая, когда вы хотите "will be" , а не will be .

Вот полная рабочая реализация (см. Результаты онлайн-демонстрации ).

 import java.util.*; import java.io.*; import java.util.regex.*; import java.util.List; class Program { public static void main (String[] args) throws java.lang.Exception { String subject = "This is a string that \"will be\" highlighted when your 'regular expression' matches something."; Pattern regex = Pattern.compile("\'[^']*'|\"[^\"]*\"|( )"); Matcher m = regex.matcher(subject); StringBuffer b= new StringBuffer(); while (m.find()) { if(m.group(1) != null) m.appendReplacement(b, "SplitHere"); else m.appendReplacement(b, m.group(0)); } m.appendTail(b); String replaced = b.toString(); String[] splits = replaced.split("SplitHere"); for (String split : splits) System.out.println(split); } // end main } // end Program 

Я уверен, что это невозможно, используя только регулярные выражения. Проверка того, что что-то содержится внутри какого-либо другого тега, – это операция синтаксического анализа. Это похоже на ту же проблему, что и попытка разобрать XML с помощью регулярного выражения – это невозможно сделать правильно. Вы можете получить желаемый результат, повторно применяя не-жадное, неглобальное регулярное выражение, которое соответствует цитируемым строкам, а затем, когда вы не можете найти что-либо еще, разделите его на пробелы …, в котором есть несколько проблемы, в том числе отслеживание первоначального порядка всех подстрок. Лучше всего просто написать действительно простую функцию, которая выполняет итерацию по строке и вытаскивает нужные вам жетоны.

Вы также можете попробовать следующее:

  String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something"; String ss[] = str.split("\"|\'"); for (int i = 0; i < ss.length; i++) { if ((i % 2) == 0) {//even String[] part1 = ss[i].split(" "); for (String pp1 : part1) { System.out.println("" + pp1); } } else {//odd System.out.println("" + ss[i]); } } 

Если вы используете c #, вы можете использовать

 string input= "This is a string that \"will be\" highlighted when your 'regular expression' matches "; List list1 = Regex.Matches(input, @"(?\w+)|\""(?[\w\s]*)""|'(?[\w\s]*)'|<(?[\w\s]*)>").Cast().Select(m => m.Groups["match"].Value).ToList(); foreach(var v in list1) Console.WriteLine(v); 

Я специально добавил « | <(? [\ W \ s] *)> », чтобы подчеркнуть, что вы можете указать любой символ для группировки фраз. (В этом случае я использую <> для группировки.

Выход:

 This is a string that will be highlighted when your regular expression matches something random 
  • Метод split () Java разбивает пустые строки в конце?
  • Разделить строку на строковый массив одиночных символов
  • Разделение строки / числа каждый N-й символ / номер?
  • Разделить строку с разделителями на C
  • Разделение столбца строки dataframe на несколько разных столбцов
  • C # Разделить строку на другую строку
  • Разделение csv-файла с кавычками как разделитель текста с помощью String.split ()
  • Строка Java, разделенная на "." (Точка)
  • Java: как разбить строку на несколько символов?
  • Как подмножество кадра данных в фактор и повторить график для каждого подмножества?
  • C ++ - многократное использование istringstream
  • Interesting Posts
    Давайте будем гением компьютера.