Регулярное выражение для разделения на пробелы, если только в кавычках
Я хотел бы использовать метод .Net Regex.Split для разделения этой входной строки на массив. Он должен разбиваться на пробелы, если он не заключен в цитату.
Input:
Вот "моя строка" она имеет "шесть символов " соответствует
Ожидаемый результат:
- Здесь
- является
- моя строка
- это
- есть
- шесть матчи
Какой шаблон мне нужен? Также мне нужно указать любые RegexOptions?
Ответы
Ответ 1
Никаких параметров не требуется
Regex:
\w+|"[\w\s]*"
С#:
Regex regex = new Regex(@"\w+|""[\w\s]*""");
Или, если вам нужно исключить символы:
Regex
.Matches(input, @"(?<match>\w+)|\""(?<match>[\w\s]*)""")
.Cast<Match>()
.Select(m => m.Groups["match"].Value)
.ToList()
.ForEach(s => Console.WriteLine(s));
Ответ 2
Решение Lieven получает большую часть пути, и, как он заявляет в своих комментариях, это просто вопрос о замене финала на решение Bartek. Конечным результатом является следующий рабочий regEx:
(?<=")\w[\w\s]*(?=")|\w+|"[\w\s]*"
Ввод: здесь "моя строка" имеет "шесть совпадений"
Вывод:
- Здесь
- является
- "моя строка"
- это
- есть
- "шесть матчей"
К сожалению, он включает в себя кавычки. Если вы используете следующее:
(("((?<token>.*?)(?<!\\)")|(?<token>[\w]+))(\s)*)
И явно зафиксируйте совпадение "токенов" следующим образом:
RegexOptions options = RegexOptions.None;
Regex regex = new Regex( @"((""((?<token>.*?)(?<!\\)"")|(?<token>[\w]+))(\s)*)", options );
string input = @" Here is ""my string"" it has "" six matches"" ";
var result = (from Match m in regex.Matches( input )
where m.Groups[ "token" ].Success
select m.Groups[ "token" ].Value).ToList();
for ( int i = 0; i < result.Count(); i++ )
{
Debug.WriteLine( string.Format( "Token[{0}]: '{1}'", i, result[ i ] ) );
}
Отладочный вывод:
Token[0]: 'Here'
Token[1]: 'is'
Token[2]: 'my string'
Token[3]: 'it'
Token[4]: 'has'
Token[5]: ' six matches'
Ответ 3
Я использовал Bartek Szabat ответ, но мне нужно было захватить больше, чем просто "\ w" персонажей в моих токенах. Чтобы решить эту проблему, я немного изменил его регулярное выражение, как и Grzenio:
Regular Expression: (?<match>[^\s"]+)|(?<match>"[^"]*")
C# String: (?<match>[^\\s\"]+)|(?<match>\"[^\"]*\")
Код Bartek (который возвращает токены, лишенные закрывающих кавычек):
Regex
.Matches(input, "(?<match>[^\\s\"]+)|(?<match>\"[^\"]*\")")
.Cast<Match>()
.Select(m => m.Groups["match"].Value)
.ToList()
.ForEach(s => Console.WriteLine(s));
Ответ 4
Главный ответ для меня не совсем подходит. Я пытался разделить эту строку на пробелы, но похоже, что она разбивается на точки ( "." ).
"the lib.lib" "another lib".lib
Я знаю, что вопрос задает вопрос о регулярных выражениях, но в итоге я написал функцию без регулярных выражений, чтобы сделать это:
/// <summary>
/// Splits the string passed in by the delimiters passed in.
/// Quoted sections are not split, and all tokens have whitespace
/// trimmed from the start and end.
public static List<string> split(string stringToSplit, params char[] delimiters)
{
List<string> results = new List<string>();
bool inQuote = false;
StringBuilder currentToken = new StringBuilder();
for (int index = 0; index < stringToSplit.Length; ++index)
{
char currentCharacter = stringToSplit[index];
if (currentCharacter == '"')
{
// When we see a ", we need to decide whether we are
// at the start or send of a quoted section...
inQuote = !inQuote;
}
else if (delimiters.Contains(currentCharacter) && inQuote == false)
{
// We've come to the end of a token, so we find the token,
// trim it and add it to the collection of results...
string result = currentToken.ToString().Trim();
if (result != "") results.Add(result);
// We start a new token...
currentToken = new StringBuilder();
}
else
{
// We've got a 'normal' character, so we add it to
// the curent token...
currentToken.Append(currentCharacter);
}
}
// We've come to the end of the string, so we add the last token...
string lastResult = currentToken.ToString().Trim();
if (lastResult != "") results.Add(lastResult);
return results;
}
Ответ 5
Я нашел регулярное выражение в этом , чтобы быть весьма полезным. Чтобы заставить его работать на С#, вам нужно будет использовать класс MatchCollection.
//need to escape \s
string pattern = "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'";
MatchCollection parsedStrings = Regex.Matches(line, pattern);
for (int i = 0; i < parsedStrings.Count; i++)
{
//print parsed strings
Console.Write(parsedStrings[i].Value + " ");
}
Console.WriteLine();
Ответ 6
Это регулярное выражение будет разделено на случай, описанный выше, хотя он не разделяет кавычки или дополнительные пробелы, поэтому вы можете захотеть выполнить некоторую пост-обработку в своих строках. Это должно правильно держать строки с кавычками вместе.
"[^"]+"|\s?\w+?\s
Ответ 7
С небольшим количеством беспорядочности регулярные языки могут отслеживать четный/нечетный подсчет кавычек, но если ваши данные могут включать экранированные кавычки (\ "), то у вас возникают реальные проблемы с созданием или пониманием регулярного выражения, которое будет правильно отрегулируйте его.
Ответ 8
EDIT: Извините за мой предыдущий пост, это, очевидно, возможно.
Чтобы обрабатывать все символы, отличные от алфавитно-цифровых символов, вам нужно что-то вроде этого:
MatchCollection matchCollection = Regex.Matches(input, @"(?<match>[^""\s]+)|\""(?<match>[^""]*)""");
foreach (Match match in matchCollection)
{
yield return match.Groups["match"].Value;
}
вы можете сделать foreach умнее, если вы используете .Net > 2.0
Ответ 9
Шон,
Я считаю, что следующее регулярное выражение должно это сделать
(?<=")\w[\w\s]*(?=")|\w+
С уважением,
Ливны
Ответ 10
Взгляните на LSteinle " Разделить функцию, которая поддерживает классификаторы текста" в проекте кода
Вот фрагмент его проекта, который вас интересует.
using System.Text.RegularExpressions;
public string[] Split(string expression, string delimiter, string qualifier, bool ignoreCase)
{
string _Statement = String.Format("{0}(?=(?:[^{1}]*{1}[^{1}]*{1})*(?![^{1}]*{1}))",
Regex.Escape(delimiter), Regex.Escape(qualifier));
RegexOptions _Options = RegexOptions.Compiled | RegexOptions.Multiline;
if (ignoreCase) _Options = _Options | RegexOptions.IgnoreCase;
Regex _Expression = New Regex(_Statement, _Options);
return _Expression.Split(expression);
}
Просто следите за вызовом этого в цикле, создавая и компилируя оператор Regex каждый раз, когда вы его вызываете. Поэтому, если вам нужно назвать это более чем несколько раз, я бы посмотрел на создание кеша регулярных выражений.
Ответ 11
Если вы хотите взглянуть на общее решение этой проблемы в виде бесплатного JavaScript-объекта с открытым исходным кодом, вы можете посетить http://splitterjsobj.sourceforge.net/ для живой демонстрации (и загрузки). Объект имеет следующие функции:
- Пары пользовательских символов кавычек могут использоваться для выхода из разделителя (предотвратить разделение внутри кавычек). Кавычки могут быть экранированы с помощью пользовательского escape файла char и/или путем "сбрасывания двойной кавычки". Побег char может быть экранирован (сам по себе). В одном из 5 выходных массивов (свойств объекта) вывод не отображается. (Например, если escape char =/, "a///" b "не отображается как /" b)
- Разделить на массив разделителей; проанализируйте файл за один вызов. (Выходные массивы будут вложенными.)
- Все escape-последовательности, распознаваемые javascript, могут быть оценены в процессе разделения и/или в препроцессе.
- Функциональность обратного вызова
- Совместимость между браузерами
Объект также доступен как плагин jQuery, но как новый пользователь на этом сайте я могу включить только одну ссылку в это сообщение.