nim語言的正則表示式regex入門
nim語言的re模組是包裝了c語言的庫pcre. 提供了很多的proc供呼叫.
主要的 函式就是find, findBounds, findAll
1. findBounds查詢某個規則的字串.
例如:
import re let currentline = "[chapter Uno] and {style} [chapter dos]." regex = re"\[chapter(\s+)(.*?)\]" proc testStrings() = var matches: seq[string] = @["", ""] let (start, e) = currentline.findbounds(regex, matches) echo "testStrings" echo "start: ", start, " end: ", e, " matches: ", matches.repr proc testStringIndices() = var matches: seq[string] matches.newSeq(2) let (start, e) = currentline.findbounds(regex, matches) echo "testIndices" echo "start: ", start, " end: ", e, " matches: ", matches.repr proc testIndices() = var matches: seq[tuple[first, last: int]] matches.newSeq(2) let (start, e) = currentline.findbounds(regex, matches) echo "testIndices" echo "start: ", start, " end: ", e, " matches: ", matches.repr when isMainModule: testStrings() testIndices() testStringIndices()
其中 findBounds 要注意的就是, 這個函式帶了一個matches 的可以過載的引數(這個引數在函式外部定義, 然後在函式內部被覆蓋數值)
尤其是要注意的是, findBounds, 只能一次找到一個符合規則的字串, 如果想找到全部的字串, 要自己寫迴圈來捕捉分組.
捕捉分組要注意的是, matches 最開始一定在定義後, 進行初始化, 如果不進行初始化, matches就不能被過載賦值.
例如
import re var ms:seq[string] ms.newSeq(2) #這裡一定要初始化, 或者使用var ms: seq[string] = @["", ""] 這種方式進行賦值初始化 var rs:tuple[first:int, last:int] var pattern:Regex = re"""href=\"(/(\w+)/(\w+).html)\"""" rs = findBounds(data, pattern, ms, 0) echo ms
如果不賦值, 例如
import re
var ms:seq[string]
#ms.newSeq(2) #這裡一定要初始化, 或者使用var ms: seq[string] = @["", ""] 這種方式進行賦值初始化
var rs:tuple[first:int, last:int]
var pattern:Regex = re"""href=\"(/(\w+)/(\w+).html)\""""
rs = findBounds(data, pattern, ms, 0)
echo ms
註釋掉之後, echo ms 就是一個空的@[]
另外, seq[string]可以用一個array進行替代,
var ms:array[2,string] #定義一個數組,型別為string, 長度為2, 這個array可以不進行初始化, 使用後可以得到合適的值.
例如:
import re
var ms:array[2,string] #ms這裡不用初始化
var rs:tuple[first:int, last:int]
var pattern:Regex = re"""href=\"(/(\w+)/(\w+).html)\""""
rs = findBounds(data, pattern, ms, 0)
echo ms
2. findBounds 找到全部符合條件的字串
直接用while寫個迴圈.
findBounds返回一個tuple,假設名為 rs, rs.first 是符合regex的第一個字元的位置, rs.last是最後一個字元的位置
echo data[rs.first..rs.last]
可以獲得第一次查詢到的字串, 這個時候, 函式已經結束,並且不再查詢後面符合條件的字串.
要找到後面符合條件的字串, 要自己寫個while函式, 不斷迴圈到資料的結尾.
例如
var ms: array[3, string] #捕獲3個組(group)
var rs:tuple[first:int, last:int]
var pattern:Regex = re"""href=\"(/(\w+)/(\w+).html)\"""" #這裡定義了3個組,順序為(全部), (子串1), (子串2)
var start = 0
rs = findBounds(data, pattern, ms, 0)
echo data[rs.first..rs.last]
while rs.first>0:
echo data[rs.first..rs.last]
echo ms
start = rs.last+1
rs = findBounds(data, pattern, ms, start)
這裡要注意的就是, nim語言的re模組沒有python的好用, python的group捕獲是自動的, 動態語言給了我們太多的方便, 這裡再nim語言就沒有這個方便了.
3. findAll
findAll 只能輸出(全部)匹配, 在(fasdf(子串1)fasdkfjl(子串2)ddsa) 這種只能輸出最長的字串(全部), 所以這裡就不要幻想有python的那麼方便了, 用完findAll, 在迴圈輸出的時候, 還要配合使用findBounds, 再進行匹配子串.
var matches:array[i, string] #i是你要匹配的子串組的個數
for line in findAll(data, regex):
findBounds(line, regex2, matches,start=0)
echo matches
以上為虛擬碼. 請自己測試.