1. 程式人生 > >nim語言的正則表示式regex入門

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

以上為虛擬碼. 請自己測試.