Regexp: подстановка номера версии в XML-файл

Хорошо, я сдаюсь, я пытался написать регулярное выражение в ant, чтобы заменить номер версии из того, что у меня есть в файле свойств. Имею следующее:

<?xml version = "1.0" encoding = "UTF-8"?>
    <feature
          id = "some.feature.id"
          label = "Some test feature"
          version = "1.0.0"
          provider-name = "Provider">

   <plugin
         id = "test.plugin"
         download-size = "0"
         install-size = "0"
         version = "0.0.0"
         unpack = "false"/>
..... many plugins later....
</feature>

Я хочу заменить только номер версии тега функции, не меняя версию xml или версию miriad плагинов в файле.

Моя проблема в том, что я либо слишком много, либо слишком мало совпадаю. Однозначного соответствия «версии» недостаточно, потому что все будет изменено

Есть ли простой способ сопоставить только версию внутри тега, учитывая, что «0.0.0» может быть любым числом?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
1 226
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Регулярное выражение подстановки Perl будет выглядеть примерно так ...

s/<feature(.*?)version = ".*?"/<featureversion = "1.2.3.4"/s

Как насчет:

<feature[^<>]+version\s*=\s*"(\d+\.\d+\.\d+)"[^<>]*>

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

Это соответствует номеру версии, но не может использоваться для Regex.Replace.

user1228 08.10.2008 16:58

Следующее регулярное выражение может делать то, что вы хотите ...

(?<=<feature[^>]{*,1000}version = ")[^"]*(? = ")

Что, на человеческом языке, примерно означает

I want to match text that immediately follows the string "<feature", followed by up to a thousand characters not the greater-than bracket, and "version = ""; the text to match is immediately followed by a double quote, and contains no double quotes.

**Спасибо Алану М за информацию о ретроспективе java. ಠ_ಠ

Если вы используете это регулярное выражение с операцией Replace, оно отключит все, что находится внутри атрибута version = "", тем, что вы установили в качестве значения замены. Вы должны предоставить правильно отформатированный номер версии.

Теперь, когда вы делаете это с помощью XML, возникает очевидный вопрос: «Почему вы не используете XPath?».

В регулярных выражениях Java каждый ретроспективный просмотр должен иметь очевидную максимальную длину, поэтому ретроспективный просмотр с [^>]* не будет компилироваться. Вы часто можете обмануть это требование, вставив произвольное число, как в [^>]{0,100}.

Alan Moore 08.10.2008 17:23

Пришлось бы добавить еще одну библиотеку в сборку ANT ... кажется излишним просто для быстрой замены ... Или я так думал, пока не увидел, насколько забавно регулярное выражение: D. Но вы правы, он лучше подходит для чего-то вроде XPath

Mario Ortegón 08.10.2008 18:36
Ответ принят как подходящий

Предполагая, что вы используете задачу replaceregexp:

<replaceregexp file = "whatever"
               match = "(<feature\b[^<>]+?version=\")[^\"]+"
               replace = "${feature.version}" />

Я также предполагаю, что есть только один элемент <feature>.

Привет! Это именно то, что я пытался сделать, но приветствую гуру регулярных выражений. Единственная проблема заключается в том, что необходимо экранировать несколько символов: match = "(<feature \ b [^ <>] +? Version = & quot;) [^ & quot;] +" И это сработало как шарм! (Изменить? Это хороший ответ!)

Mario Ortegón 08.10.2008 19:59

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

Mario Ortegón 08.10.2008 20:01

Ах да: XML ускользает! По крайней мере, я не забыл дублировать все обратные косые черты, как я привык делать в строковых литералах Java. : - /

Alan Moore 09.10.2008 05:21

На помощь приходит Vim:

:s/\(label = ".+"\_.\s*version = "\).+"/NEWVERSIONNUMBER"/

Просто для удовольствия: однострочный, используя xpath (!), С Рубин

(Я знаю: это не регулярное выражение, но оно предназначено для иллюстрации предложения Уилла, который говорит

Now, since you're doing this with XML, the obvious question is, "Why aren't you using XPath?

)

введите irb, затем:
требовать "rexml / document"; включать REXML; file = File.new ("a.xml"); doc = Document.new (файл); помещает документ; doc.elements.each ("/ feature") {| e | e.attributes ["версия"] = "1.2.3"}; помещает документ

Он заменяет все атрибуты "версия" всех элементов "функции" на "1.2.3".

irb(main):001:0* require "rexml/document";include REXML;file = File.new("a.xml"); doc = Document.new(file);puts doc; doc.elements.each("/feature") {|e| e.attributes["version"] = "1.2.3" }; puts doc

<?xml version='1.0' encoding='UTF-8'?>
<feature id='some.feature.id' version='1.0.0' provider-name='Provider' label='Some test feature'>
   <plugin unpack='false' id='test.plugin' download-size='0' version='0.0.0' install-size='0'/>
</feature>


<?xml version='1.0' encoding='UTF-8'?>
<feature id='some.feature.id' version='1.2.3' provider-name='Provider' label='Some test feature'>
   <plugin unpack='false' id='test.plugin' download-size='0' version='0.0.0' install-size='0'/>
</feature>

Это может быть немного тяжеловесно, но, поскольку вы имеете дело с XML, я бы рекомендовал использовать XSLT следующим образом:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
    <xsl:template match = "@*|*">
        <xsl:copy>
            <xsl:apply-templates select = "node()|@*|*"/>
        </xsl:copy>
    </xsl:template>


    <xsl:template match = "/feature/@version">
        <xsl:attribute name = "version">
            <xsl:text>1.0.1</xsl:text>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Другие вопросы по теме