2010-09-23 4 views
11

У меня есть эта строка (Java 1.5):Как разбить строку на Java и сохранить разделители?

:alpha;beta:gamma;delta 

Мне нужно, чтобы получить массив:

{":alpha", ";beta", ":gamma", ";delta"} 

Самый удобный способ сделать это в Java?

+0

Я редактировал название вашего вопроса, так что он становится более общим – Bozho

ответ

26
str.split("(?=[:;])") 

Это даст вам желаемый массив, только с пустым первым предметом. И:

str.split("(?=\\b[:;])") 

Это даст массив без пустого первого элемента.

  • Ключевой момент здесь является (?=X), который является нулевой шириной положительного опережения (не отлов конструктом) (см regex pattern docs).
  • [:;] означает «либо; или:»
  • \b это слово граница - это там, чтобы не рассматривать первый : как разделитель (так как это начало последовательности)
+0

'(? = X)' является «позицией с нулевой шириной», группа, не захватывающая захват, является '(?: X)'. Это не сработает корректно с группой, не участвующей в захвате ... –

+0

@ Карлос Хаубергер не мог бы вы объяснить больше? Он действительно работает таким образом (протестировал его), но я, возможно, пропустил что-то – Bozho

+1

, он работает, но последовательность '(? = X)' не называется «не захватывающей группой» или, по крайней мере, не простой «группой, не захватывающей», , Он называется «позицией с нулевой шириной». «Не захватывающая группа» - это '(?: X)'. (извините за мой плохой английский) –

4

Чтобы сепараторов, вы можете использовать StringTokenizer:

new StringTokenizer(":alpha;beta:gamma;delta", ":;", true) 

Это даст разделители в качестве маркеров.

Чтобы использовать их как часть ваших жетонов, вы можете использовать String#split с lookahead.

+3

«StringTokenizer является устаревшим классом» – Bozho

+3

@Bozho Верно, но я думаю, что этот конкретный случай использования сохранения разделителей не распространяется очень красиво струнным #split, для чего требуется некоторое подробное знание регулярных выражений. –

+0

true, это немного яснее с StringTokenizer, так как он имеет желаемую опцию в качестве логического параметра. +1, вопрос о том, чтобы быть устаревшим, все еще действителен. – Bozho

-1

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

String toSplit = ":alpha;beta:gamma;delta " 
toSplit = toSplit.replace(":", "~:") 
toSplit = toSplit.replace(";", "~;") 
//repeat for all you possible seperators 
String[] splitStrings = toSplit.split("~") 
+0

это проще. – Joset

+0

1. Это неверно, так как возвращает пустой 0-й элемент. 2. Это увеличивает вероятность ошибки из-за дублирования (т. Е. «:» Должно быть сопряжено с «~:»). 3. Что, если специальный разделитель «~» используется в одной из подстрок? –

+0

@Tony, я выбрал «~» в качестве примера, но можно использовать любой другой уникальный разделитель, подходящий для имеющегося набора данных. Я не совсем понимаю, как это увеличивает вероятность ошибки - возможно, вы могли бы прояснить этот момент. Я признаю, что он оставляет пустой 0-й элемент, который является отказом от этого подхода, но я хотел представить другой вариант, который не полагался на regex. – chillysapien

1

Вы можете сделать это, просто используя шаблоны и класс Сличитель в Java regx.

public static String[] mysplit(String text) 
    { 
    List<String> s = new ArrayList<String>(); 
    Matcher m = Pattern.compile("(:|;)\\w+").matcher(text); 
    while(m.find()) { 
    s.add(m.group()); 
    } 
    return s.toArray(new String[s.size()]); 
    } 
+0

Как только regexp djinni выходит из бутылки, я предпочитаю решение Божо. –

+0

Yup .. я согласен ... выше было просто альтернативным способом: – Favonius

1
/** 
* @param list an empty String list. used for internal purpose. 
* @param str String which has to be processed. 
* @return Splited String Array with delimiters. 
*/ 
public String[] split(ArrayList<String> list, String str){ 
    for(int i = str.length()-1 ; i >=0 ; i--){ 
    if(!Character.isLetterOrDigit((str.charAt(i)))) { 
     list.add(str.substring(i, str.length())); 
     split(list,str.substring(0,i)); 
     break; 
    } 
    } 
    return list.toArray(new String[list.size()]); 
} 
+1

Это еще один способ! для тех, кто не знает о регулярном выражении, как я :) –

0

Это должно работать с Java 1.5 (Pattern.quote был введен в Java 1.5).

// Split the string on delimiter, but don't delete the delimiter 
private String[] splitStringOnDelimiter(String text, String delimiter, String safeSequence){ 
    // A temporary delimiter must be added as Java split method deletes the delimiter 

    // for safeSequence use something that doesn't occur in your texts 
    text=text.replaceAll(Pattern.quote(delimiter), safeSequence+delimiter); 
    return text.split(Pattern.quote(safeSequence)); 
} 

Если первый элемент является проблема:

private String[] splitStringOnDelimiter(String text, String delimiter, String safeSequence){ 
    text=text.replaceAll(Pattern.quote(delimiter), safeSequence+delimiter); 
    String[] tempArray = text.split(Pattern.quote(safeSequence)); 
    String[] returnArray = new String[tempArray.length-1]; 
    System.arraycopy(tempArray, 1, returnArray, 0, returnArray.length); 
    return returnArray; 
} 

Э.Г., Здесь "а" разделитель:

splitStringOnDelimiter("-asd-asd-g----10-9asdas jadd", "a", "<>") 

Вы получаете это:

1.: - 
2.: asd- 
3.: asd-g----10-9 
4.: asd 
5.: as j 
6.: add 

Если вы на самом деле хотите это:

1.: -a 
2.: sd-a 
3.: sd-g----10-9a 
4.: sda 
5.: s ja 
6.: dd 

Вы переключаетесь:

safeSequence+delimiter 

с

delimiter+safeSequence 
Смежные вопросы