Regex Multiple lines
I try to write regex for multiple lines parsing. Here, this is powerfull example…
Idea
I want classify a set of regex into various category. Regex can be single line or mutiple line.
<regex> <line>file not found</line> </regex>
<regex> <select> <start>There was 1 failure:</start> <end>FAILURES!!!</end> </select> </regex>
For each expression, I can associate a type, title, message. And, the final configuration is :
<xml> <check> <title>IT error</title> <type>it</type> <message>File not found</message> <regex> <line>file not found</line> </regex> </check> </xml>
I thinks this example is clear enough to understand the functionnaly if you take a couple of second to look at the example.
Sources
Input
def source = """\ [java] Libary io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- library Spice file spice/io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr_ctypical_25c_5U1x_2T8x_LB.spice: retained. [java] Library io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- library Spice file spice/io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr_cworst_125c_5U1x_2T8x_LB.spice: retained. [java] Library io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- library Spice file spice/io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr_cbest_25c_5U1x_2T8x_LB.spice: retained. [java] Library io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- Siliconsmart IBIS merge char point ibis-characterizer/normal/.ibis_merge: skipped. [java] Library io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- SiliconSmart configure.tcl file ibis-characterizer/normal/merge/config/configure.tcl: skipped. [java] Library io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr -- Merged 3 PVT IBIS file ibis/io_gppr_cmos32lp_t18_mv11_mv18_tl25_rvt_dr.ibs: skipped. [java] [java] Checking library... [java] Program done. [java] file not found [java] Test Finished: testIOIBISOnly3PvtMerge, Time: 2010/03/10 04:53:30.257000000 [java] Java Vendor: Sun Microsystems Inc. [java] Java Version: 1.6.0_11 [java] Operating System: Linux [java] Total Run Time: 10354.774 Seconds [java] F [java] Time: 10,355.323 [java] There was 1 failure: [java] 1) testIOIBISOnly3PvtMerge(com.arm.cellbuilder.iotest.TestIOCellBuilder)junit.framework.AssertionFailedError: Logs from gold/test doesn't match [java] at com.arm.cellbuilder.iotest.TestIOCellBuilder.checkLogs(TestIOCellBuilder.java:1416) [java] at com.arm.cellbuilder.iotest.TestIOCellBuilder.testIOIBISOnly3PvtMerge(TestIOCellBuilder.java:1147) [java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [java] at com.arm.cellbuilder.iotest.TestIOCellBuilder.main(TestIOCellBuilder.java:75) [java] [java] FAILURES!!! [java] Tests run: 1, Failures: 1, Errors: 0 [java] BUILD SUCCESSFUL Total time: 172 minutes 40 seconds ERROR"""
Configuration
def config = """\
<xml>
<check>
<title>IT error</title>
<type>it</type>
<message>File not found</message>
<regex>
<line>file not found</line>
</regex>
</check>
<check>
<title>JUnit stacktrace</title>
<type>developer</type>
<message>JUnit</message>
<regex>
<select>
<start>There was 1 failure:</start>
<end>FAILURES!!!</end>
</select>
</regex>
</check>
</xml>
"""
Groovy
def checker = { input, configuration -> // TODO: Apply selector one by one def conf = new XmlParser().parseText(configuration) def stats = [] //TODO: Check if title unique def modeMultiline = false // Read file line by line input.eachLine{ line -> def title = "" def message = "" conf.check.each{ title = it.title.text() message = it.message.text() assert title // Single line error detection if(!modeMultiline){ it.regex.line.each{ if(line ==~ /^.*${it.text()}.*$/){ stats << title println message } } } // Select interesting part of the report it.regex.select.each{ if(!modeMultiline){ if(line ==~ /^.*${it.start.text()}.*$/){ modeMultiline = true println "${message} >>>>>>" } }else{ if(line ==~ /^.*${it.end.text()}.*$/){ modeMultiline = false stats << title println "<<<<<<<<" }else{ if(line ==~ /^.*[java].*/ && line.size() > 8) println line.substring(9) } } } } } return stats } def stats = checker(source, config) assert stats.size() == 2 // Associate title -> type def map = [:] stats.each{ title -> new XmlParser().parseText(config).check.each{ if(it.title.text() == title){ if(map[it.title.text()] == null){ map[it.type.text()] = 1 }else{ map[it.type.text()]++ } } } } // Display result map.each{ key, value -> println "${key}:${value}" }
Conclusion
It works perfectly and more over the execution time is really efficient…