https://blog.csdn.net/yxp_xa/article/details/72466333
在1956 年,一位名叫 Stephen Kleene 的数学科学家,发表了一篇《神经网事件的表示法》的论文,论文中采用正则集合的数学符号来模拟人类神经系统的工作原理。后来人们将这一成果转化到计算机算法中,将其变成了一门文本搜索和处理的语言。
正则表达式(Regular Express ),可以按字面意思理解,正确的符合规则的表式。
在 CAD 的二次开发中,简单的文字匹配可以用 Lisp 自带的 wcmatch 函数,但是这个函数返回值只有 T 或 NIL。 如果需要返回匹配后的相关字符时,或者稍微复杂一点的文字匹配, wcmatch 就无能为力了。
深入地学习正则表达式的语法还是有些难度的,我用的是偷懒的办法,只写最简单的正则语法,对于复杂的正则语法网上都能搜到。但无论怎样,前提是要弄清楚正则的属性和方法。
创建正则对象
在AutoCAD中创建正则表达式对象:
(setq RegObj (vlax-create-object "vbscript.regexp"))
对象创建成功时,可以用以下代码检查 RegObj 对象支持的属性和方法:
(vlax-dump-object RegObj t)
返回如下:
;特性值:
; Global = 0
; IgnoreCase = 0
; Multiline = 0
; Pattern = ""
;支持的方法:
; Execute (1)
; Replace (2)
; Test (1)
可以发现,正则对象支持的 4 个属性和 3 个方法,其组织结构图如下:
属性
正则表达式支持的属性有 4 个,分别为 Global、IgnoreCase、Multiline、Pattern
Global 全局搜索
默认值为 0,正则引擎默认搜索到第一个关键字后停止;如果需要全局搜索,可将其属性设置为 1,代码如下:
(vlax-put-property RegObj 'Global 1)
IgnoreCase 大小写敏感
默认值为 0,敏感模式,即搜索时区分大小写;如需忽略大小写代码如下:
(vlax-put-property RegObj 'IgnoreCase 1)
Multiline 多段搜索
默认 0,不分段。此参数仅对元字符^和$
(开始和结束)有影响
当设置为 1 时,^|$ 代表每行的开始或结束
(vlax-put-property RegObj 'Multiline 1)
Pattern 搜索时的描述字符串
正则表达式的核心参数,正则表达式变化多样的语法靠此参数实现
例如:不含换行符的任意字符
(vlax-put-property RegObj 'Pattern ".")
方法
正则表达式支持的方法有 3个,分别为 Execute、Replace、Test
Test 方法
测试目标文本中,是否包含正则表达式所描述的字符串(即 Pattern 参数)。
(vlax-invoke RegObj 'Test "abcefg")
Replace 方法
在目标文本中用正则表达式查找到的字符串替换,并返回替换结果。
例如用 “=” 替换字符串中的 “c”
(vlax-put-property RegObj 'Pattern "c")
(vlax-invoke RegObj 'Replace "abcefg" "=")
返回 “ab=efg”
变量分组
来看这一段文字:”白菜20萝卜56土豆31茄子47”,我们需要为数字后加一个单位 “kg,”
(vlax-put-property RegObj 'Pattern "\\w+")
(vlax-invoke RegObj 'Replace "白菜20萝卜56土豆31茄子47" "kg,")
返回 “白菜kg,萝卜kg,土豆kg,茄子kg,”
结果把数字也替换掉了,怎么办?我们需要匹配的字符串出现在它原来的地方,实现插入字符串的效果。这时候就需要用到变量的分组,用 “$1” 代表第一组正则 Pattern , Pattern 语法单元需要用 () 分组,每对括号代表1组变量。
(vlax-put-property RegObj 'Pattern "(\\w+)")
(vlax-invoke RegObj 'Replace "白菜20萝卜56土豆31茄子47" "$1kg,")
返回 “白菜20kg,萝卜56kg,土豆31kg,茄子47kg,”
变量分组最多可以支持到 99 组。
Execute 方法
在目标文本中执行正则表达式搜索。 返回一个 Matches 对象集合,该集合具有
count 属性(匹配次数)、 item 属性(项索引),以及一个 matche 对象
(vlax-put-property RegObj 'Pattern "\\w+")
(setq mat (vlax-invoke RegObj 'Execute "我们we你们you这儿here那儿there"))
检查 count 属性
(vlax-get-property mat 'count)
返回 4,即匹配了 4次
检查 item 的第一项
(vla-get-value (vlax-get-property mat 'item 0))
返回第一个匹配的对象 we
如需所有对象的值,可以用 vlax-for 函数遍历 matche 对象集合,该对象具有四个属性,但我们只需要 value 属性。
(setq L nil)
(vlax-for x mat (setq L (cons (vla-get-value x) L)))
返回:(“there” “here” “you” “we”)
举一个简单的栗子
(defun test (s p / L)
(setq r (vlax-create-object "vbscript.regexp"))
(vlax-put-property r 'Global 1)
(vlax-put-property r 'Pattern p)
(vlax-for x (vlax-invoke r 'Execute s)(setq L (cons (vla-get-value x) L)))
(vlax-release-object r)
(reverse L)
)
以下代码实现中英文按字符分离的效果:
(test "我爱CAD" ".")
返回 (“我” “爱” “C” “A” “D”)
如果需要中英文按词组分离,只需要设置不同的 Pattern 属性即可。
(test "我爱CAD你喜欢CAD吗" "([\\u4e00-\\u9fa5])+|([a-zA-Z])+")
返回 (“我爱” “CAD” “你喜欢” “CAD” “吗”)