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
以上為僞代碼. 請自己測試.
參考資料: https://forum.nim-lang.org/t/593