Использование функции reshape
:
reshape(dat1, idvar = "name", timevar = "numbers", direction = "wide")
Я не понимаю, почему все остальные предлагают такие сложные регулярные выражения или такой длинный код. По сути, вы хотите захватить два типа вещей из вашей строки: последовательности символов, которые не являются пробелами или кавычками, и последовательности символов, которые начинаются и заканчиваются цитатой, без кавычек между ними, для двух видов кавычек. Вы можете легко сопоставить эти вещи с этим регулярным выражением:
[^\s"']+|"([^"]*)"|'([^']*)'
Я добавил группы захвата, потому что вам не нужны кавычки в списке.
Этот код Java создает список, добавив группу захвата, если она соответствует, чтобы исключить кавычки, и добавление общего соответствия регулярному выражению, если группа захвата не совпала (несогласованное слово было сопоставлено).
List<String> matchList = new ArrayList<String>();
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());
}
}
t mind с кавычками в возвращенном списке, вы можете использовать гораздо более простой код:
List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
matchList.add(regexMatcher.group());
}
подход Яна велик, но вот еще один для записи.
Если вы действительно хотели разделить, как указано в заголовке, сохраняя кавычки в "will be"
и 'regular expression'
, вы можете использовать этот метод, который прямо из Match (или replace) шаблон, за исключением ситуаций s1, s2, s3 и т. д.
Регулярное выражение:
'[^']*'|\"[^\"]*\"|( )
Два левых чередования соответствуют полному 'quoted strings'
и "double-quoted strings"
. Мы проигнорируем эти матчи. Правая сторона сопоставляет и фиксирует пробелы в группе 1, и мы знаем, что они являются правильными пространствами, потому что они не соответствовали выражениям слева. Мы заменим их на 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
Если вы используете c #, вы можете использовать
string input= "This is a string that \"will be\" highlighted when your 'regular expression' matches <something random>";
List<string> list1 =
Regex.Matches(input, @"(?<match>\w+)|\""(?<match>[\w\s]*)""|'(?<match>[\w\s]*)'|<(?<match>[\w\s]*)>").Cast<Match>().Select(m => m.Groups["match"].Value).ToList();
foreach(var v in list1)
Console.WriteLine(v);
Я специально добавил «| & lt; (? [\ w \ s] *)>", чтобы подчеркнуть, что вы можете указать любой символ группировать фразы. (В этом случае я использую & lt;> для группировки.
Выход:
This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something random
Мне понравился подход Маркуса, однако я изменил его, чтобы я мог разрешить текст рядом с кавычками и поддерживать оба символа «и». Например, мне было нужно a = «некоторое значение», чтобы не разбить его на [a =, "некоторое значение"].
(?<!\\G\\S{0,99999}[\"'].{0,99999})\\s|(?<=\\G\\S{0,99999}\".{0,99999}\"\\S{0,99999})\\s|(?<=\\G\\S{0,99999}'.{0,99999}'\\S{0,99999})\\s"
Вероятно, будет легче искать строку, захватывая каждую часть, а также разделять ее.
Причина, вы можете разбить ее на пробелы до и после "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"
(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s
Это будет соответствовать пробелам, не окруженным двойными кавычками. Я должен использовать min, max {0,99999}, потому что Java не поддерживает * и + в lookbehind.
Если вы хотите разрешить экранированные кавычки внутри строки, вы можете использовать что-то вроде этого:
(?:(['"])(.*?)(?<!\\)(?>\\\\)*\1|([^\s]+))
Цитированные строки будут группой 2, одиночные некотируемые слова будут группой 3.
Вы можете попробовать его на разных строках здесь: http://www.fileformat.info/tool/regex.htm или http://gskinner.com/RegExr/
Пару надеемся на полезные рекомендации по принятому ответу Яна:
(['"])((?:\\\1|.)+?)\1|([^\s"']+)
Вы также можете попробовать следующее:
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]);
}
}
Я уверен, что это невозможно, используя только регулярные выражения. Проверка того, что что-то содержится внутри какого-либо другого тега, - это операция синтаксического анализа. Это похоже на ту же проблему, что и попытка разобрать XML с помощью регулярного выражения - это невозможно сделать правильно. Вы можете получить желаемый результат, повторно применяя не-жадное, неглобальное регулярное выражение, которое соответствует цитируемым строкам, а затем, когда вы не можете найти что-либо еще, разделите его на пробелы ..., в котором есть несколько проблемы, в том числе отслеживание первоначального порядка всех подстрок. Лучше всего написать просто простую функцию, которая выполняет итерацию по строке и вытаскивает нужные вам жетоны.
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."
\"
? – Monstieur 6 May 2014 в 15:19John's mother
, расщепленные в[John, s, mother]
– leonbloy 16 May 2014 в 21:10"([^"]*)"|'([^']*)'|[^\s]+
. – Ghostkeeper 15 September 2014 в 02:26