java
  • regex
  • replace
  • 2013-04-03 3 views 0 likes 
    0

    У меня есть рисунок как: <[a-zA-Z][^>]*(?:poster|src)=(['\"])([^'\"]+)\\1[^>]*> здесь я хочу заменить значение атрибутов src или poster.Регулярное выражение заменить две группы

    Это ОКЕЙ для

    <video src='srcVal' /> 
    

    и

    <video poster='posterVal' src='srcVal' /> 
    

    но

    <video poster='posterVal' src='srcVal' /> 
    

    только изменяет значение Src, из-за matcher.group(2) возвращения только srcVal.

    public class Test { 
        public static void main(String[] args) throws Exception { 
         String html = "<video poster='posterVal' src='srcVal' />"; 
         Pattern resourcePattern = Pattern.compile("<[a-zA-Z][^>]*(?:poster|src)=(['\"])([^'\"]+)\\1[^>]*>"); 
         Matcher matcher = resourcePattern.matcher(html); 
         int last = 0; 
         StringBuilder sb = new StringBuilder(); 
         while(matcher.find()) { 
          String path = matcher.group(2) + "Changed"; 
          sb.append(html.substring(last, matcher.start(2)) + path); 
          last = matcher.end(2); 
         } 
         sb.append(html.substring(last)); 
         System.out.println(sb); 
         //outputs <video poster='posterVal' src='srcValChanged' /> 
         //expecting <video poster='posterValChanged' src='srcValChanged' /> 
        } 
    } 
    

    Есть ли у кого-нибудь идеи, как это сделать?

    +0

    Попробуйте посмотреть здесь: [Java Regex] (http://www.vogella.com/articles/JavaRegularExpressions/article.html) – Justin

    +2

    Я бы не рекомендовал использовать регулярные выражения, когда вы занимаетесь структурой языка, а не точное представление как текст. То есть вы разбираете диалект XML, а в XML порядок атрибутов не имеет значения - но регулярные выражения не могут легко представить «порядок не имеет значения». Используйте настоящую библиотеку XML, ее очень много. – drquicksilver

    +0

    Они не могут легко, но все же, они могут. Lookaheads и условное регулярное выражение - это два инструмента, которые можно использовать для достижения таких целей. – Loamhoof

    ответ

    0

    я бы не сделать это с помощью регулярных выражений, но вы можете попробовать такую ​​вещь:

    <[a-zA-Z]*[^>]*(?:(poster)|src)=(['\"])([^'\"]+)\\2(?(1)[^>]*(?:src=(['\"])([^'\"]+)\\4)?[^>]*|[^>]*(?:poster=(['\"])([^'\"]+)\\6)?[^>]*)> 
    

    Хотя у меня нет времени, чтобы проверить это, как сейчас, извините.

    Edit:
    Меньше ориентированных на производительность:

    <[a-zA-Z]*(?=(?:[^>]*?poster=['\"]([^'\"]+))?)(?=(?:[^>]*?src=['\"]([^'\"]+))?)[^>]*(?:poster|src)[^>]*> 
    

    Если вы хотите, чтобы соответствовать видео теги, изменить его (как это было бы значительно улучшить его):

    <video(?=(?:[^>]*?poster=['\"]([^'\"]+))?)(?=(?:[^>]*?src=['\"]([^'\"]+))?)[^>]*(?:poster|src)[^>]*> 
    

    Пояснение: (как я полагаю, он должен выглядеть довольно тревожным)

    Мы используем 2 взгляда, чтобы захватить то, что интересно. Lookaheads позволит нам дважды проверить, что произойдет, поэтому игнорируем заказ. Однако эти взгляды всегда должны работать (используя * и?, Чтобы убедиться в этом), но все же являясь жадным, будучи ленивым (что?): Мы должны остановиться, как только мы увидим плакат/src, но идем достаточно далеко, чтобы поймать их. .*?a? всегда ничего не поймает. Поэтому мы используем здесь (?:.*?a)?.Поведение здесь состоит в том, чтобы попытаться поймать a с лени, а если он терпит неудачу, это не проблема.
    Последняя часть регулярного выражения состоит в том, чтобы убедиться, что мы улавливаем только теги с плакатом или атрибутом src, так как наши взгляды делают это только для ловушек и, конечно же, не могут быть использованы для этого.

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

    +0

    Думаю, я понимаю, как вы хотите это сделать, но он жалуется на (? (1) ...) часть. Благодарю. – yavuzkavus

    +0

    Черт, я думал, что Java поддерживает условное регулярное выражение. Я подумаю. – Loamhoof

    +0

    @ yavuzkavus проверен в javascript, он работает как шарм. – Loamhoof

    0

    Основная проблема с [^>]* в начале вашего выражения. Поскольку * жаден это будет съедать столько символов, сколько он может в то же время позволяя остальной части выражения, чтобы соответствовать, поэтому данный

    <video poster='posterVal' src='srcVal' /> 
    

    в [^>]* сожрет ideo poster='posterVal' до и включая пространство перед src=.

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

    html.replaceAll("\\b((?:poster|src)=)(['\"])([^'\"]+)\\1", "$1$2$3Changed$2") 
    

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

    +0

    Это не столько его проблема. Он хочет захватить оба, независимо от порядка. – Loamhoof

    +0

    если у меня есть html, например src = "my.png", он изменит обычный текст, а не только атрибуты элемента. – yavuzkavus

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