Хорошо, я сдаюсь, я пытался написать регулярное выражение в 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» может быть любым числом?




Регулярное выражение подстановки Perl будет выглядеть примерно так ...
s/<feature(.*?)version = ".*?"/<featureversion = "1.2.3.4"/s
Как насчет:
<feature[^<>]+version\s*=\s*"(\d+\.\d+\.\d+)"[^<>]*>
В скобках указана группа, соответствующая номеру версии. Перемещайте круглые скобки, чтобы получить точное соответствие, которое вам нужно.
Следующее регулярное выражение может делать то, что вы хотите ...
(?<=<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}.
Пришлось бы добавить еще одну библиотеку в сборку ANT ... кажется излишним просто для быстрой замены ... Или я так думал, пока не увидел, насколько забавно регулярное выражение: D. Но вы правы, он лучше подходит для чего-то вроде XPath
Предполагая, что вы используете задачу replaceregexp:
<replaceregexp file = "whatever"
match = "(<feature\b[^<>]+?version=\")[^\"]+"
replace = "${feature.version}" />
Я также предполагаю, что есть только один элемент <feature>.
Привет! Это именно то, что я пытался сделать, но приветствую гуру регулярных выражений. Единственная проблема заключается в том, что необходимо экранировать несколько символов: match = "(<feature \ b [^ <>] +? Version = & quot;) [^ & quot;] +" И это сработало как шарм! (Изменить? Это хороший ответ!)
Как будто синтаксис регулярного выражения был недостаточно загадочным, добавьте немного экранирования: D
Ах да: XML ускользает! По крайней мере, я не забыл дублировать все обратные косые черты, как я привык делать в строковых литералах Java. : - /
На помощь приходит 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>
Это соответствует номеру версии, но не может использоваться для Regex.Replace.