在VLISP中使用正则表达式(一)取多行文字中的有用内容
我将在以后有空的时间,为大家写一些看起来深一点的知识。正则表达式,就是使用“Vbscript.RegExp”控件进行文字的查找和替换操作。
普通的文字查找与替换,只能做到替换特定的字符,而不能按照特定的特征进行替换。
例如:一段文字中,需要将“明经通道”几个字都替换为“明经CAD社区”,那直接用替换就可以。
但如果我们有一篇文字,其中需要将“第XX章”全部修改为“第XX节”,而且XX是变化的,需要替换的数量非常多,这时用普通的替换就无能为力了。
这时,我们就得用上正则表达式了。
其实为什么正则表达式在AutoCAD中还没有人提到过使用,那就是因为使用AutoCAD并不是以使用文字为主,所以总少人去研究。但正则表达式在网络编程中使用非常广泛,正如大家看到本站可以大家输入的代码进行语法着色,使用的就是“正则表达式”的功能。呵呵,够强大吧。
在AutoCAD中,也经常会出现象一些明细表、技术要求等之类的文字内容,也会经常碰到过模糊替换的问题。所以多学一些知识是有好处的。
好了,先给大家获取多行文字中的有用字符的LISP代码吧,其实这个代码在几年前已经用VBA解决。而且用LISP的普通代码应该也能解决这样的问题,但如果用正则表达式,则会显得清晰明了。
下一节将会讲一些有关正则表达式的使用方法。 (vl-load-com)
(defun c:m2txt(/ s )
(setq s "{\\C3;\\{明经通{\\fSimSun|b0|i0|c134|p2;道\\}}\\Lhttp://www.mjtd.com{\\C3;明经通道\\Lhttp{\\C1;://{\\C3;www}.mjtd.com}\\l是一个好网站啊,呵呵}\\l是{\\Ftxt.shx,gbcbig.shx|c134;一个好网站}啊,呵呵}")
(setq mtext(vlax-ename->vla-object(car(entsel "\n选择多行文字:"))))
(if (=(vla-get-objectname mtext) "AcDbMText")
(progn
(vla-put-textstring mtext s)
(setq s (vla-get-textstring mtext))
(setq s (mtext2text s))
(princ "\n")
(princ s)
)
(princ "\n出错")
)
(princ)
)
(defun mtext2text(MTextString / regex s)
(setq regex(vlax-create-object "Vbscript.RegExp")) ;引用正则表达式控件
(vlax-put-property regex "IgnoreCase" 0) ;不忽略大小写
(vlax-put-property regex "Global" 1) ;匹配方式,全文字匹配
(setq s MTextString)
;替换\\字符
(vlax-put-property regex "Pattern" "\\\\\\\\")
(setq s(vlax-invoke-methodregex "Replace" s (chr 1)))
;替换\{字符
(vlax-put-property regex "Pattern" "\\\\{")
(setq s(vlax-invoke-methodregex "Replace" s (chr 2)))
;替换\}字符
(vlax-put-property regex "Pattern" "\\\\}")
(setq s(vlax-invoke-methodregex "Replace" s (chr 3)))
;删除段落缩进格式
(vlax-put-property regex "Pattern" "\\\\pi(.[^;]*);")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除制表符格式
(vlax-put-property regex "Pattern" "\\\\pt(.[^;]*);")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除堆迭格式
(vlax-put-property regex "Pattern" "\\\\S(.[^;]*)(\\^|#|\\\\)(.[^;]*);")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除字体、颜色、字高、字距、倾斜、字宽、对齐格式
(vlax-put-property regex "Pattern" "(\\\\F|\\\\f|\\\\C|\\\\H|\\\\\T|\\\\Q|\\\\W|\\\\A)(.[^;]*);")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除下划线、删除线格式
(vlax-put-property regex "Pattern" "(\\\\L|\\\\O|\\\\l|\\\\o)")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除不间断空格格式
(vlax-put-property regex "Pattern" "\\\\~")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除换行符格式
(vlax-put-property regex "Pattern" "\\\\P")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除换行符格式(针对Shift+Enter格式)
(vlax-put-property regex "Pattern" "\n")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;删除{}
(vlax-put-property regex "Pattern" "({|})")
(setq s(vlax-invoke-methodregex "Replace" s ""))
;替换回\\,\{,\}字符
(vlax-put-property regex "Pattern" "\\x01")
(setq s(vlax-invoke-methodregex "Replace" s "\\"))
(vlax-put-property regex "Pattern" "\\x02")
(setq s(vlax-invoke-methodregex "Replace" s "{"))
(vlax-put-property regex "Pattern" "\\x03")
(setq s(vlax-invoke-methodregex "Replace" s "}"))
(vlax-release-object regex)
s
)
从程序可以看到,多行文字原来的内容是:
其实际文字内容是:
{\\C3;\\{明经通{\\fSimSun|b0|i0|c134|p2;道\\}}\\Lhttp://www.mjtd.com{\\C3;明经通道\\Lhttp{\\C1;://{\\C3;www}.mjtd.com}\\l是一个好网站啊,呵呵}\\l是{\\Ftxt.shx,gbcbig.shx|c134;一个好网站}啊,呵呵}
经过替换后剩下了:
{明经通道}http://www.mjtd.com明经通道http://www.mjtd.com是一个好网站啊,呵呵是一个好网站啊,呵呵
怎么取多行文字中的第2行 感谢大神支持! <p>请问版主,你的程式是否可以支持通配符“*”的替换呢?</p><p>比如:把“A1BCD" "A1BBD" "A1BDD"同一使用通配符"A2*D"替换成“A2BCE" "A2BBE" "A2BDE"呢?</p><p>如果可以,请大侠指导小弟一把如何使用</p><p>谢谢</p><p> </p> 本帖最后由 作者 于 2007-1-15 21:27:38 编辑 <br /><br /> <p>这简直是太简单了,因为正则表达式就是专门为这一类的替换设计的:</p><p>(defun c:replacetxt(/ regex s txtstring)<br/> (setq regex(vlax-create-object "Vbscript.RegExp"));引用正则表达式控件<br/> (vlax-put-property regex "IgnoreCase" 0); 不忽略大小写<br/> (vlax-put-property regex "Global" 1);全文匹配,而不是只匹配第一处<br/> (setq txtstring "A1BCD A1BBD A1BDD ")<br/> (setq s txtstring)<br/> ;替换字符<br/> (vlax-put-property regex "Pattern" "A1(.{2})D")<br/> (setq s(vlax-invoke-method regex "Replace" s "A2$1E"))<br/> <br/> (vlax-release-object regex)<br/> (princ (strcat "\n替换前为:" txtstring))<br/> (princ (strcat "\n替换后为:" s))<br/> (princ)<br/>)</p><p>程序运行结果:<br/>命令: REPLACETXT<br/>替换前为:A1BCD A1BBD A1BDD<br/>替换后为:A2BCE A2BBE A2BDE<br/></p> <p>好,以后多学学</p><p>谢谢斑竹</p> <p>看来,以后要加紧学习了</p> <p>谢谢版主,会更努力学习的</p><p></p> <p>版主,你的程式好像不好使呀,执行完了没有反应呀</p><p>还有(setq txtstring "A1BCD A1BBD A1BDD")</p><p>如果需要替换的文字很多,一一写出来比较麻烦的情况下如何解决呢?能不能不用写入"A1BCD A1BBD A1BDD"字符串呢?</p><p>如果可以该如何实现呢?麻烦版主多指教。</p> <p>你来个图形文件给试试,你需要做到什么样的操作,选择文字直接替换还是其它。</p><p>其实这只教大家一个方法,其它的可以自己加上去,如选择文字,或选择属性块中的文字,可直接打开文件替换等。这些都可以自己写的。关键要掌握方法。</p> <p>版主所言甚是,可小弟新手初来乍到,不熟悉,还请多多执教</p><p> </p><p></p><p>比如我需要把“S3NP33A”改成“S1NP33L”而且类似这样的修改还很多,所以我想请版主帮帮忙,做一个能用通配符"*"的替换lisp的文件,</p><p>完成S3*A替换成S1*L而且以*替代的字符串内容不变。如何修改你的程式?请执教</p> 本帖最后由 作者 于 2007-1-17 13:18:54 编辑
(defun c:reptxt(/ regex s seltext i objtext oldtext)
(princ"\n明经通道文本模糊替换示例--将S3*A替换为S1*L")
(setq seltext(ssget "X" '((0 . "TEXT"))))
(ifseltext
(progn
(setq i 0)
(setq regex(vlax-create-object "Vbscript.RegExp"));引用正则表达式控件
(vlax-put-property regex "IgnoreCase" 0); 不忽略大小写
(vlax-put-property regex "Global" 1);全文匹配,而不是只匹配第一处
(repeat (sslength seltext)
(setq objtext(vlax-ename->vla-object (ssname seltext i)))
(setq s (vla-get-textstring objtext))
(setq oldtext s)
;替换字符
(vlax-put-property regex "Pattern" "S3(.{4})A")
(setq s(vlax-invoke-methodregex "Replace" s "S1$1L"))
(vla-put-textstring objtext s)
(if (/= oldtext s)
(progn
(princ (strcat "\n替换前为:" oldtext))
(princ (strcat "\n替换后为:" s))
)
)
(setq i(1+ i))
)
(vlax-release-object regex)
)
)
(princ)
)