Разделите строку, используя несколько разделителей в java [duplicate]

Использование функции reshape:

reshape(dat1, idvar = "name", timevar = "numbers", direction = "wide")
94
задан Jason Plank 3 August 2011 в 20:05
поделиться

13 ответов

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

[^\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());
} 
210
ответ дан Alan Moore 22 August 2018 в 11:12
поделиться
  • 1
    Ян, спасибо за ваш ответ. Кстати, я большой поклонник EditPad. – carlsz 14 December 2008 в 17:05
  • 2
    Я знаю, что это было 3 года спустя, но это очень помогло мне. – Speck 12 October 2011 в 17:10
  • 3
    Что делать, если я хочу разрешить скрытые кавычки в строках \"? – Monstieur 6 May 2014 в 15:19
  • 4
    Проблема с этим ответом заключается в непревзойденной цитате: результаты John's mother, расщепленные в [John, s, mother] – leonbloy 16 May 2014 в 21:10
  • 5
    Чтобы исправить проблемы leonbloy, вы можете немного изменить порядок операндов и опустить кавычки из группы пробелов: "([^"]*)"|'([^']*)'|[^\s]+. – Ghostkeeper 15 September 2014 в 02:26

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

Если вы действительно хотели разделить, как указано в заголовке, сохраняя кавычки в "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
12
ответ дан Community 22 August 2018 в 11:12
поделиться
  • 1
    Я думаю, что ваше регулярное выражение допускает несогласованные кавычки, например. «будут» и «регулярные выражения». – Zach Scrivena 14 December 2008 в 08:05
  • 2
    @Zach - вы правы, это так ... обновил его, чтобы исправить это на всякий случай – Jay 14 December 2008 в 08:36

Если вы используете 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
0
ответ дан daniele3004 22 August 2018 в 11:12
поделиться
  • 1
    Если у вас есть новый вопрос, спросите его, нажав кнопку Ask Question . Включите ссылку на этот вопрос, если это поможет обеспечить контекст. - Из обзора – Mr Spoon 23 November 2017 в 13:32

Мне понравился подход Маркуса, однако я изменил его, чтобы я мог разрешить текст рядом с кавычками и поддерживать оба символа «и». Например, мне было нужно 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"
1
ответ дан Eric Woodruff 22 August 2018 в 11:12
поделиться
3
ответ дан iRon 22 August 2018 в 11:12
поделиться

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

Причина, вы можете разбить ее на пробелы до и после "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"
1
ответ дан Jonathan Lonowski 22 August 2018 в 11:12
поделиться
  • 1
    Ваше решение не обрабатывает строки с одной кавычкой, которые являются частью примера Карла. – Jan Goyvaerts 14 December 2008 в 14:08
(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s

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

2
ответ дан Marcus Andromeda 22 August 2018 в 11:12
поделиться

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

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

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

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

5
ответ дан mcrumley 22 August 2018 в 11:12
поделиться

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

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

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

    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]);
        }
    }
0
ответ дан Rakesh Sosa 22 August 2018 в 11:12
поделиться
  • 1
    Вы должны действительно добавить некоторые объяснения относительно того, почему это должно сработать - вы также можете добавить код, а также комментарии в самом коде - в его текущей форме он не дает никаких объяснений, которые могут помочь остальному сообществу понять, что вы сделали, чтобы решить / ответить на вопрос. Это особенно важно для вопросов, на которые уже есть ответы. – ishmaelMakitla 12 September 2016 в 14:13

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

0
ответ дан rmeador 22 August 2018 в 11:12
поделиться
  • 1
  • 2
    Знайте, когда не использовать regex - это более полезное знание, чтобы иметь возможность создавать (?: (['& Quot;]) (. *?) (? & Lt;! \) (? & Gt; \\\) * \ 1 | ([^ \ s] +)) – Rene 14 December 2008 в 16:43

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."
1
ответ дан Zach Scrivena 22 August 2018 в 11:12
поделиться
12
ответ дан Community 5 November 2018 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: