最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Groovy正則表達式使用解讀

 更新時間:2025年09月07日 14:15:57   作者:Allocator  
文章總結(jié)了Groovy中的正則表達式特點,指出其作為Java擴展支持=~和==~操作符,轉(zhuǎn)義字符使用需特別處理,正則表達式在雙引號字符串中不需要轉(zhuǎn)義,但需雙斜線表示特殊字符,與Java相比,Groovy更簡便,基于Pattern和Matcher類,用于模式匹配和捕獲子字符串

背景

項目使用Gradle作為自動化構(gòu)建的工具, 閑暇之余對這個工具的使用方式以及其配置文件依賴的Groovy語法進行了鞏固, 在學(xué)習(xí)Groovy語法的時候發(fā)現(xiàn)其中一個比較有意思的東西, 就是Groovy的正則表達式,于是本篇文章總結(jié)了一下Groovy中的正則表達式的特點以及Groovy正則表達式與Java正則表達式的區(qū)別:

Groovy正則表達式語法

Groovy是Java語言的一種擴展, 可以無縫的使用Java的JDK, 并且其自身還有SDK對Java進行了擴展. Groovy中的正則表達式本質(zhì)上還是會使用到JDK中的java.lang.regex 包中的class, 其實這一部分, 個人認為可以看成一種"語法糖", 只不過更方便大家在Groovy中使用正則表達式

來看一個最簡單的正則表達式

def reg1 = ~'he*llo'
def reg2 = /he*llo/
println "reg1 type is ${reg1.class}"
println "reg2 type is ${reg2.class}"
println "hello".matches(reg1)
println "hello".matches(reg2)

運行結(jié)果:

reg1 type is class java.util.regex.Pattern
reg2 type is class java.lang.String
true
true

上式中使用了~ + 字符串(以及雙斜線分隔符模式)的方式定義了一個正則表達式

Groovy中支持使用~ 來定義正則表達式, 打印出來的reg 類型都為Pattern 類型而不是一個字符串, 需要注意的點是上述例子中的~= 之間有一個空格, 因為Groovy中存在=~ 操作符號, 這個操作符為查詢操作符, 使用在字符串之后, 要求接一個正則表達式, 返回的是一個java.util.regex.Matcher 對象. 還有一個操作符==~ 也比較容易混淆,這個操作符為匹配操作符, 后面跟一個正則表達式, 返回的類型為Boolean 類型. 這個操作符要求前面給定的字符串與后面的正則表達式完全匹配才可返回true 比如以下的列子

def val1 = "hello" =~ "he*llo"
println val1.class
print val1.matches()

運行結(jié)果

class java.util.regex.Matcher
true

使用Groovy中的匹配操作符可以簡化上述的操作

def val1 = "hello" ==~ "he*llo"
println val1.class
print val1

運行結(jié)果:

class java.lang.Boolean
true

原字符問題

我們知道正則表達式中存在一些特殊的字符(比如\w 表示的是[a-zA-Z0-9])用于文本的匹配, 這些字符一般是以\ 開頭, 所以這個地方涉及到了轉(zhuǎn)義字符問題.

舉個例子:

def val1 = "test value"
println 'value is ${val1}'
println "value is ${val1}"

運行結(jié)果:

value is ${val1}
value is test value

如果在構(gòu)建正則表達式字符串的時候, 使用雙引號表示字符串,就需要使用\\ 來表示單斜線,比如:

def reg1 = "hello \\w*"
def reg2 = /hello \w*/
println "hello world" ==~ reg1
println "hello world" ==~ reg2

運行結(jié)果為true 當(dāng)然使用雙斜線字符串的話就不需要額外的斜線進行轉(zhuǎn)義. 我們知道groovy的單引號中的字符串是以原字符的形式存在的,即是字符串本身就是它顯示的意思,嘗試使用單引號原字符來進行正則匹配:

def reg1 = 'hello \w*' // 更改為 'hello \\w*' 則運行正確
println "hello world" ==~ reg1

但是最終卻是一個error 使用單引號依然需要進行轉(zhuǎn)義, 仔細想想,Groovy的單引號場景是參數(shù)解析的場景, 而此處是含有斜線的正則表達式字符的匹配問題, 兩個問題應(yīng)該不一樣,因此無論是使用單引號還是雙引號,遇到正則表達式的含有斜線的特殊字符都要進行轉(zhuǎn)義.不想進行轉(zhuǎn)義可以使用斜線取代(單)雙引號.

Pattern 和 Matcher

在Groovy中正則表達式中相關(guān)聯(lián)的依然是這兩個Java類. 依然回歸到Java中的這兩個類. JDK1.8 中java.util.regex 包中最核心的就是這兩個類, Pattern表示的即是正則表達式的"模式", 這是一個抽象的概念, 在編程過程中我們使用的是字符串表示正則, 它只是一種抽象的模式,實際上需要將字符串表示的抽象模式"編譯"成這個類才能夠正常工作, 當(dāng)在Groovy中可以理解為使用~ 操作符將字符串編譯為一個Pattern對象. 回顧這個類中的一些重要的概念和方法:

Pattern.matches 和 Pattern.matcher

Matcher matcher(charsequence input)

這個函數(shù)返回一個Matcher匹配器對象, 這個匹配器匹配給定的輸入與模式

def reg = ~/^hello \w*world$/
def str = "hello world"
def matcher = reg.matcher(str)
println matcher.class

輸出的類型就是java.util.regex.Matcher 然而上述的Matcher對象在groovy中可以用=~ 操作符號一步完成

def matcher = "hello world"=~/^hello \w*world$/
println matcher.class
static boolean matches(string regex, charsequence input)

這個函數(shù)編譯給定的正則表達式并且嘗試匹配給定的輸入, 這個在Java中是一個靜態(tài)的函數(shù), 可以理解為一種快速判斷字符串與給定的正則表達式模式是否匹配的工具, 同樣在Groovy中也有簡單的實現(xiàn)方式

println "hello world"==~/^hello \w*world$/

運行結(jié)果為true 可以看到Groovy中使用兩個操作符號=~==~ 完成了Matcher匹配對象的構(gòu)建, 以及快速驗證給定字符串是否和給定正則表達式模式匹配的功能.

Matcher 中的capturing group概念

首先Matcher 的概念是解釋Pattern. 我理解的是有時候我們使用正則表達式不僅僅是完成簡單的驗證字符串是否和模式匹配, 而是需要更加靈活和高級的操作(比如獲取部分匹配成功的子字符串功能), 此時就需要這個Matcher對象. Java中需要調(diào)用Pattern中的matcher方法返回這個對象, 而groovy中只需要使用=~ 操作符號即可創(chuàng)建這樣的對象.抽象的講, 這個對象即是存儲一個正則表達式模式與一個給定輸入字符串的所有匹配相關(guān)的信息. capturing group 這個概念是針對正則表達式中的() 引入的, 正則表達式中的括號表示group,捕獲組是從左往右計算其開始括號進行編號的(因為具有括號嵌套的情況, 括號層次越高那么它的組編號自然越小), 其中0表示整個表達式,

如下例子:

(A (BC))
group 0: (A(BC))
group 1: (A(BC))
group 2: (BC)

計算表達式的group就從左括號開始算遇到一個左括號group number就加1. 使用group可以用于捕獲輸入字符串與模式匹配上的部分對應(yīng)group位置的子字符串.

def str = "hello wrold hello"
def reg = /((el)(l))o/
def matcher = str=~reg
def num = 0
while(matcher.find()){
    println "the ${num} match sub sequenc"
    num++
    groupnum = matcher.groupCount()
    println "group count ${matcher.groupCount()}"
    println "group string ${matcher.group()}"
    println "group 0 string ${matcher.group(0)}"
    for(id in 1..groupnum){
        println "group ${id} string ${matcher.group(id)}"
        println "start index is ${matcher.start(id)} and end index is ${matcher.end(id)}"
    }
}

運行結(jié)果:

the 0 match sub sequenc
group count 3
group string ello
group 0 string ello
group 1 string ell
start index is 1 and end index is 4
group 2 string el
start index is 1 and end index is 3
group 3 string l
start index is 3 and end index is 4
the 1 match sub sequenc
group count 3
group string ello
group 0 string ello
group 1 string ell
start index is 13 and end index is 16
group 2 string el
start index is 13 and end index is 15
group 3 string l
start index is 15 and end index is 16

有一個點比較重要就是groupCount 組數(shù)量是不會將group 0計算在內(nèi)的,組的數(shù)量是和括號數(shù)量保持一致, 其次是matcher.group() 方法和matcher.group(0) 方法返回內(nèi)容都一樣, 都是和模式匹配的完成的子序列, 當(dāng)傳遞參數(shù)時返回的就是相應(yīng)編號的捕獲組獲取的子序列.當(dāng)然可以使用start end等方法獲取到匹配的字符串(或者捕獲組匹配到的字符串)的偏移量(end的偏移量位置始終是最后一個字符的位置加1).

注意在groovy中由于GDK實現(xiàn)了getAt 方法那么其實可以通過索引的方式訪問捕獲組中的內(nèi)容,如下例子:

def reg = ~/h(el)(lo)/
def str = 'hello world hello nihao'
def matcher = str=~reg
println "first matched substring"
println matcher[0]
println matcher[0][0]
println matcher[0][1]
println matcher[0][2]
println "second matched substring"
println matcher[0]
println matcher[0][0]
println matcher[0][1]
println matcher[0][2]

運行結(jié)果

first matched substring
[hello, el, lo]
hello
el
lo
second matched substring
[hello, el, lo]
hello
el
lo

可以看到通過索引訪問捕獲字符串的規(guī)律, 返回的matcher對象第一維度索引表示子字符串的索引, 返回值為一個ArrayList 包含的內(nèi)容是全部的子字符串以及與捕獲組編號對應(yīng)的子字符串. 這些等價的操作即是matcher.group(index)

Matcher 重置

匹配器的重置涉及到兩個方法find()reset 其中find 方法可以指定從哪一個位置重新開始尋找模式匹配的字符串.比如:

def reg = /el/
def str = "hello world hello"
def matcher = str=~reg
while(matcher.find()){
    println matcher.group()
}
matcher.find(0) // 重置matcher 從頭開始尋找匹配字符串
// 但此時第一個匹配的子字符串已經(jīng)獲取到了,下一次調(diào)用find則是查詢下一個匹配字符串
println "reset the matcher"
while(matcher.find()){
    println matcher.group()
}

結(jié)果:

el
el
reset the matcher
el

當(dāng)然最好使用reset來完成這個過程:

def reg = /el/
def str = "hello world hello"
def matcher = str=~reg
while(matcher.find()){
    println matcher.group()
}
matcher.reset()
println "reset the matcher"
while(matcher.find()){
    println matcher.group()
}

輸出結(jié)果:

el
el
reset the matcher
el
el

總結(jié)

以上就是Groovy中的正則表達式一些比較常見的知識點, 主要是Groovy中特有的操作符號來構(gòu)建正則表達式使用過程中依賴的各種對象.

最本質(zhì)的還是回歸到j(luò)ava中正則表達式相關(guān)的兩個核心類(Pattern和Matcher). Groovy有時候表現(xiàn)得更像是一種"語法糖", 以腳本的方式來完成Java的編程.

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • spring容器啟動實現(xiàn)初始化某個方法(init)

    spring容器啟動實現(xiàn)初始化某個方法(init)

    這篇文章主要介紹了spring容器啟動實現(xiàn)初始化某個方法(init),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java8中Function接口的使用方法詳解

    Java8中Function接口的使用方法詳解

    在 Java 8 中,Function 接口是 java.util.function 包中的一個函數(shù)式接口,函數(shù)式接口是僅包含一個抽象方法的接口,適用于 Lambda 表達式或方法引用,本文給大家介紹了Java8的Function接口的使用方法,需要的朋友可以參考下
    2024-09-09
  • java自定義類加載器代碼示例

    java自定義類加載器代碼示例

    這篇文章主要介紹了java自定義類加載器代碼示例,具有一定借鑒價值,需要的朋友可以了解下。
    2017-12-12
  • SpringCloudAlibaba整合Feign實現(xiàn)遠程HTTP調(diào)用的簡單示例

    SpringCloudAlibaba整合Feign實現(xiàn)遠程HTTP調(diào)用的簡單示例

    這篇文章主要介紹了SpringCloudAlibaba 整合 Feign 實現(xiàn)遠程 HTTP 調(diào)用,文章中使用的是OpenFeign,是Spring社區(qū)開發(fā)的組件,需要的朋友可以參考下
    2021-09-09
  • 淺談Maven鏡像更換為阿里云中央倉庫(精)

    淺談Maven鏡像更換為阿里云中央倉庫(精)

    本篇文章主要介紹了Maven鏡像更換為阿里云中央倉庫(精),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java的CyclicBarrier循環(huán)屏障解析

    Java的CyclicBarrier循環(huán)屏障解析

    這篇文章主要介紹了Java的CyclicBarrier循環(huán)屏障解析,CyclicBarrier和CountDownLatch一樣,是一個同步工具類,它允許一組線程相互等待直到達到某個common?barrier?point,在程序中CyclicBarrier是非常有用的,它適用于一組線程必須互相等待的情況,需要的朋友可以參考下
    2023-12-12
  • Spring?Security+JWT簡述(附源碼)

    Spring?Security+JWT簡述(附源碼)

    SpringSecurity是一個強大的可高度定制的認證和授權(quán)框架,對于Spring應(yīng)用來說它是一套Web安全標準,下面這篇文章主要給大家介紹了關(guān)于Spring?Security+JWT簡述的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • java基礎(chǔ)的詳細了解第四天

    java基礎(chǔ)的詳細了解第四天

    這篇文章對Java編程語言的基礎(chǔ)知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來幫助
    2021-08-08
  • Mybatis-Plus多表關(guān)聯(lián)查詢的使用案例解析

    Mybatis-Plus多表關(guān)聯(lián)查詢的使用案例解析

    這篇文章主要介紹了Mybatis-Plus多表關(guān)聯(lián)查詢的使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 詳解Java雙軸快速排序算法

    詳解Java雙軸快速排序算法

    在排序算法中,快速排序是占比非常多的一環(huán),但是快速排序其思想一直被考察研究,也有很多的優(yōu)化方案。這里主要講解雙軸快速排序的思想和實現(xiàn)
    2021-06-06

最新評論

富阳市| 香港 | 施甸县| 师宗县| 边坝县| 富川| 边坝县| 嫩江县| 长寿区| 荆州市| 高碑店市| 沧源| 南召县| 玉龙| 湘乡市| 喀什市| 武安市| 连城县| 余庆县| 蒲江县| 南和县| 翼城县| 曲周县| 寿宁县| 信丰县| 灌阳县| 阳山县| 望江县| 镇宁| 加查县| 从江县| 浠水县| 开封市| 昌图县| 宜君县| 五原县| 吴旗县| 湛江市| 清徐县| 建昌县| 巴塘县|