Regex за намиране на двойки низове

Намерих този страхотен gant скрипт на http://blog.armbruster-it.de/2010/07/getting-a-list-of-all-i18n-properties-used-in-a-grails-application/ Благодаря Стефан!

Описание: създайте списък на всички i18n свойства, използвани в groovy код и gsp шаблони

def properties = []

new File(".").eachFileRecurse {
    if (it.file) {
        switch (it) {
            case ~/.*\.groovy/:
                def matcher = it.text =~ /code:\s*["'](.*?)["']/
                matcher.each { properties << it[1] }
                break
            case ~/.*\.gsp/:
                def matcher = it.text =~ /code=["'](.*?)["']/
                matcher.each { properties << it[1] }
                break
        }
    }
}
println properties.sort().unique().join("\n")

Опитах се да го разширя по следния начин. Да кажем, че имаме някои свойства на съобщението като:

message(code: 'product.label', default: 'Product')

Това, което искаме да имаме като резултат от скрипта, нещо като:

product.label=Product

Опитах се да добавя някакво условие към регулярния израз:

def matcher = it.text =~ /code=["'](.*?)["'] | default=\s*["'](.*?)["']/

и да го попълните в свойства. Но тъй като регулярният израз не намира двойки части "код и по подразбиране", това няма да работи.

Някаква идея как да промените регулярния израз или целия скрипт, за да направите това?


person skurt    schedule 19.04.2011    source източник


Отговори (4)


Вашият регулярен израз е неправилен. За следното извикване на метод на съобщение:

message(code: 'product.label', default: 'Product')

Трябва да изглежда така:

def properties = [:]
def txt = "message(code: 'product.label', default: 'Product')"
def matcher = txt =~ /code:\s*["'](.*?)["'].*default:\s*["'](.*?)["']/
matcher.each{ properties[it[1]] = it[2] }
assert properties == ['product.label':'Product']
person Kai Sternad    schedule 19.04.2011
comment
ups, прочетох вашето решение, след като публикувах моето. почти същото и работи, благодаря! - person skurt; 20.04.2011
comment
докато работих с този код, изпитвам известна слабост: намира само едно съвпадение на ред код. За да поправим това, трябва да променим съвпадението. - person skurt; 26.04.2011
comment
Доколкото разбирам, той дори не разглежда редове, а целия текст и всъщност намира множество съвпадения за мен. Проблемът е, че (a) намира само съвпадения, които имат стойност по подразбиране и игнорира тези без и (b) игнорира факта, че понякога ще трябва да използвате ${g.message(…)} и в .gsp файлове . - person fluxon; 11.03.2013

Освен предоставянето на по-добър регулярен израз, както направи bunting, намерих доста полезна добавка за Grails: message-reports

person Stefan Armbruster    schedule 19.04.2011
comment
но едно нещо трябва да добавя. Това, което търсих, е по-скоро скрипт, който ми дава всички кодове заедно с неговите настройки по подразбиране. Тъй като нашето приложение не е използвало i18n досега, всички низове трябва да бъдат разделени от кода. Ще опитам какво могат да направят групите в регулярния израз, за ​​да реша това. - person skurt; 20.04.2011

по-добрият регулярен израз за решаването му е:

/code=["'](.*?)["'].*default=\s*["'](.*?)["']/

изходен формат може да бъде

properties << it[1]+"="+it[2]

резултати

product.label=Product
person skurt    schedule 20.04.2011

Поработих малко с този скрипт и открих някои подробности, на които трябваше да се обърне внимание. Искам да намеря съобщения със и без дефинирани стойности по подразбиране и искам да намеря и версията без етикет (т.е. ${g.message(code:"the.code", default:"the.default"}).

Изглежда добре да не преглеждате съдържанието на файла, а да го анализирате ред по ред. Това е така, защото ако има код в ред, аз (във втора стъпка) ще погледна дали има стойност по подразбиране. Все пак не искам да анализирам целия файл два пъти.

def properties = [:]

new File(".").eachFileRecurse { file ->
    if (file.file) {
        switch (file) {
            case ~/.*\.groovy/:
                file.eachLine {line ->
                    // check if there is a message in the current line
                    def matcherNoDefault = line =~ /code:\s*["'](.*?)["']/
                    // if there is one, check if it has a default
                    if (matcherNoDefault.getCount() > 0) {
                        def matcher = line =~ /code:\s*["'](.*?)["'].*default:\s*["'](.*?)["']/
                        if (matcher.getCount() > 0) {
                            matcher.each{ properties[it[1]] = it[2] }
                        } else {
                            matcherNoDefault.each{ properties[it[1]] = "NO_DEFAULT" }
                        }
                    }
                }
                break
            case ~/.*\.gsp/:
                file.eachLine {line ->
                    // check if there is a message in the current line (as a g.message(...) function)
                    def matcherNoDefault = line =~ /code:\s*["'](.*?)["']/
                    // if there is one, check if it has a default
                    if (matcherNoDefault.getCount() > 0) {
                        def matcher = line =~ /code:\s*["'](.*?)["'].*default:\s*["'](.*?)["']/
                        if (matcher.getCount() > 0) {
                            matcher.each{ properties[it[1]] = it[2] }
                        } else {
                            matcherNoDefault.each{ properties[it[1]] = "NO_DEFAULT" }
                        }
                    }

                    // check if there is a message in the current line (in tag form)
                    matcherNoDefault = line =~ /code=["'](.*?)["']/
                    // if there is one, check if it has a default
                    if (matcherNoDefault.getCount() > 0) {
                        def matcher = line =~ /code=["'](.*?)["'].*default=["'](.*?)["']/
                        if (matcher.getCount() > 0) {
                            matcher.each{ properties[it[1]] = it[2] }
                        } else {
                            matcherNoDefault.each{ properties[it[1]] = "NO_DEFAULT" }
                        }
                    }
                }
        }
    }
}
println properties.each {k, v ->
    println("${k}=${v}")
}

По този начин не мога да смесвам съобщения със и без подразбиране в един ред. Мога да живея с това засега.

Забавлявай се!

person fluxon    schedule 11.03.2013