2013-03-04 7 views
0

Я разбором каким-нибудь текстом в Java с Regexпростого атрибут разбора с закодированными двойными кавычками

У меня есть строки, которые выглядят следующим образом: myAttribute = «некоторый текст», и я разбор их как этот

Pattern attributePattern = Pattern.compile("[a-z0-9]*=\"[^\"]*\""); 

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

например. myAttribute = «текст с двойной цитатой \» здесь»

Как настроить мое регулярное выражение для обработки этого

Вот мой код, который анализирует атрибуты

private HashMap<String, String> findAttributes(String macroAttributes) { 
    Matcher matcher = attributePattern.matcher(macroAttributes); 
    HashMap<String, String> map = new HashMap<String, String>(); 
    while (matcher.find()) { 
     String attribute = macroAttributes.substring(matcher.start(), matcher.end()); 
     int equalsIndex = attribute.indexOf("="); 
     String attrName = attribute.substring(0, equalsIndex); 
     String attrValue = attribute.substring(equalsIndex+2, attribute.length()-1); 
     map.put(attrName, attrValue); 
    } 
    return map; 
} 

findAttributes("my=\"some text with a double quote \\\" here\""); 

Если возвращать карту размер 1 Значение должно быть какой-то текст с двойной цитатой \»здесь

ответ

1

Вы можете использовать чередование и положительное утверждение для просмотра назад, что

Pattern attributePattern = Pattern.compile("[a-z0-9]*=\"(?:[^\"]*|(?<=\\\\)\")*\""); 

(?:[^\"]*|(?<=\\\\)\")* представляет собой чередование, либо соответствие [^\"]* или (?<=\\\\)\"

(?<=\\\\)\" сопрягает а», но только если он предшествует люфта.

+0

Ваше решение работал отлично! Я вижу, что теперь мне нужно сбежать от нормальных слэшей, но это нормально. Многие tx –

1

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

myAttribute="some text with a trailing backslash \\" 

Если это возможно, попробовать что-то вроде этого:

Pattern.compile("[a-zA-Z0-9]+=\"([^\"\\\\]|\\\\[\"\\\\])*\"") 

быстрое объяснение:

[a-zA-Z0-9]+  # the key 
=    # a literal '=' 
\"    # a literal '"' 
(    # start group 
    [^\"\\\\]  # any char except '\' and '"' 
    |    # OR 
    \\\\[\"\\\\] # either '\\' or '\"' 
)*    # end group and repeat zero or more times 
\"    # a literal '"' 

быстрая демонстрация:

public class Main { 

    private static HashMap<String, String> findAttributes(Pattern p, String macroAttributes) { 
     Matcher matcher = p.matcher(macroAttributes); 
     HashMap<String, String> map = new HashMap<String, String>(); 
     while (matcher.find()) { 
      map.put(matcher.group(1), matcher.group(2)); 
     } 
     return map; 
    } 

    public static void main(String[] args) { 
     final String text = "my=\"some text with a double quote \\\" here\""; 
     System.out.println(findAttributes(Pattern.compile("([a-z0-9]+)=\"((?:[^\"\\\\]|\\\\[\"\\\\])*)\""), text)); 
     System.out.println(findAttributes(Pattern.compile("([a-z0-9]*)=\"((?:[^\"]*|(?<=\\\\)\")*)\""), text)); 
    } 
} 

напечатает:

{my=some text with a double quote \" here} 
{my=some text with a double quote \}
+0

Спасибо, я тестировал этот шаблон, но он, похоже, не работал. Я поставил некоторый пример кода в вопрос, чтобы показать, что я сейчас делаю. С вашей моделью все еще кажется, что она заканчивается ». Кажется, что Штема предположила, что это работает, поэтому я отметил его как правильное. (Если вы исправите, я с радостью дам вам преимущество для вашего времени и усилий) –

+0

@BruceLowe, я просто протестировал его, и он работает как шарм. Оформить демонстрацию, которую я опубликовал. –

+0

@BruceLowe, и обратите внимание, что вы можете использовать [match-groups] (http://www.regular-expressions.info /brackets.html), чтобы извлечь ключи и значения (вам не нужно делать какие-либо подстроки). –

Смежные вопросы