2015-07-01 2 views
5

Я прочитал эту строку из файла:Как разбить строку с помощью java regex с внешним видом?

abc | а (а \ | а) | Защита

Я хочу, чтобы получить массив inludes 3 пунктов:

  1. AbC
  2. а (ABC \ | ABC)
  3. Защиту

Как правильно писать регулярное выражение? line.split("(?!<=\\)\\|") не работает.

+0

Что такое ваш сплит? Это '|', которое находится в скобках, или '|', которые перед этим не имеют '' '' '? Также может быть строка 'abc \ | abc | (ab | ab) '? Или даже 'ab \\ | ab \ | ab'? Если да, как вы хотите разбить его? – Pshemo

+0

похоже, что вам просто нужно разделить на | персонаж. Если это то, что вы хотите, вы можете просто использовать String [] splitedArray = str.split ("\\ |"); –

+0

@RamanShrivastava Это не так просто. Также OP уже расщепляется на '\\ |'. – Pshemo

ответ

2

Код:

public class __QuickTester { 

    public static void main (String [] args) { 

     String test = "abc|abc (abc\\|abc)|def|banana\\|apple|orange"; 

     // \\\\ becomes \\ <-- String 
     // \\ becomes \ <-- In Regex 
     String[] result = test.split("(?<!\\\\)\\|"); 

     for(String part : result) { 
      System.out.println(part); 
     } 
    } 
} 

Выход:

abc 
abc (abc\|abc) 
def 
banana\|apple 
orange 


Примечание: Вам нужно \\\\ (4 обратной косой черты), чтобы получить \\ (2 обратной косой черты) в виде строки, а затем \\ (2 обратных косых черт) становится одним \ в Regex.

+0

Но строка может inculde «abc | abc», я обновляю свой пост – mystdeim

+0

@mystdeim Без пробелов сейчас, и он работает! Я думаю, что сейчас это правильно. :) – Gosu

0

попробовать это регулярное выражение: ([\w()]|(\\|))+

0

Главная проблема в вашем подходе является то, что \ особенного в регулярном выражении, но и в String. Таким образом, чтобы создать \ буквальные вам нужно бежать дважды:

  • в регулярном выражении \\
  • в строках "\\\\".

так что вам нужно будет написать это как split("(?<!\\\\)\\|")

Но есть также возможные проблемы с этим подходом, поскольку расщепление на |, который просто предшествует \ может быть подвержен ошибкам. Поскольку вы используете \ в качестве специального символа для создания \ буквально, вам, вероятно, нужно будет написать его как \\, например, для создания c:\foo\bar\ вам, вероятно, нужно будет записать его в тексте как c:\\foo\\bar\\.

Так что в этом случае позволяет говорить о том, что вы хотите разделить текст как

abc|foo\|c:\\bar\\|cde 

Я предполагаю, что вы хотите разделить только на это ставит

abc|foo\|c:\\bar\\|cde 
^   ^

потому

  • в abc|foo труба | нет \ перед этим,
  • в bar\\|cde несмотря на трубу, имеющую \ перед ним, мы знаем, что это \ не был использован, чтобы избежать |, но генерировать текст, представляющий \ буквальным (так обычно |, которые имеют не или даже количество \ символов ОК разделить на).

Но split(onEachPipeWhichHaveBackslashBeforeIt) как split("(?<!\\\\)\\|") вы не разделены между bar\\|cde, потому что есть \ перед тем |, который позволит предотвратить такое разделение.

Для решения этой проблемы вы можете проверить, есть ли нечетное число \ до |, но это трудно сделать на Java, так как look-behind должен иметь ограниченную ширину.

Возможное решение: split("(?<!(?<!\\\\)((\\\\){2}){0,1000}\\\\)\\|") и предположение, что строка никогда не будет содержать более 1000 непрерывных \ символов, но это похоже на излишний шум.

ИМО лучшее решение будет искать строки, которые вы хотите найти, вместо поиска строк, которые вы хотите разбить. А строки, которые вы хотите найти в

  • все символы кроме |
  • все символы, которые предшествуют \ (включая | так \ просто избежать его).

Таким образом, наше регулярное выражение может выглядеть (\\\\.|[^|])+ (я поместил \\\\. при запуске, чтобы предотвратить [^|] потребляя \, который будет использоваться, чтобы избежать других символов).

Пример:

Pattern p = Pattern.compile("(\\\\.|[^|])+"); 
Matcher m = p.matcher(text); 
while (m.find()){ 
    System.out.println(m.group()); 
} 

Выход:

abc 
foo\|c:\\bar\\ 
cde 
Смежные вопросы