简介面向AutoCAD二次开发与LISP编程学习者这是一份AutoLISP常用函数分类速查手册。内容按数学运算、检验与逻辑运算、转换运算、列表处理等模块编排覆盖(、-、*、/)、1、1-、abs、expt、sqrt等数学函数、、、and、eq、equal等逻辑判断函数angtof、rtos、trans等转换函数以及car、cdr、cons、member等经典列表操作函数每个函数均给出完整的语法格式与返回值说明便于快速查阅和对比记忆。资源为单个PDF文件体积仅47KB轻量便携可随时离线检索特别适合新手入门时对照学习也适合有经验开发者案头备查。目前已有763人浏览学习。通过该手册读者能在编写AutoCAD脚本或二次开发程序时快速确认函数用法减少查找时间同时借助分类结构加深对LISP函数式写法的理解从容应对坐标计算、单位换算、批量数据处理等常见场景提升开发效率。1. LISP函数大全分类手册从“查字典”到“会写程序”这份AutoLISP速查表够用某个设计单位的老哥拿到一套别人写的批量标注程序想改标注前缀盯着car、cdr、caddr看了半小时没敢动。他不是不会 LISP是不知道去哪查——在线文档太散、范例太碎。这份按用途分类的 AutoLISP 函数手册价值就在于把数学、逻辑、列表、字符串、几何、对象、选择集、流程控制、错误处理等十九个大类的函数全摊开按“我要干什么”去查而不是按字母去翻。新手拿它当索引熟手拿它对照参数边界写程序时翻一页就能落地。2. 数学与逻辑运算先把数值、比较和位运算的底层逻辑捋顺AutoLISP 的数学函数看着简单但踩坑点全在细节整数除法的截断、三角函数的角度单位、fix到底是“截断”还是“四舍五入”。这一章把这些边界一次说清。2.1 数学函数从加减乘除到 sqrt、expt 的精度与弧度细节最基本的四则运算很多初学者以为(/ 17 5)会返回 3.4实际返回 3。AutoLISP 里两个整数相除结果是整数小数部分直接舍掉不是四舍五入。想让结果带小数至少把一个操作数写成实数(setq a 17 b 5) (setq sum ( a b)) ; 22加法可传多个参数 (setq diff (- a b)) ; 12 (setq prod (* a b)) ; 85 (setq quot (/ a b)) ; 3整数除法截断不是四舍五入 (setq q2 (/ a 2.0)) ; 8.5除法只要有一个实参结果就是实数 (setq r (rem a b)) ; 2余数 (setq g (gcd 12 8)) ; 4最大公因数 (setq s (sqrt 2.0)) ; 1.41421平方根rem和gcd在工程场景里用得不多但做参数化建模时比如生成螺栓阵列要判断“能否整除”这两个函数比手写循环快得多。fix的坑在精度(fix 3.99)返回 3它是向零取整不是四舍五入。想要四舍五入得自己加 0.5 再 fix。三角函数是重灾区。手册里写着(sin 角度)返回值是“角度值为弧度”但实际操作中经常有人直接(sin 30)期望得到 0.5结果得到的是 -0.988因为 30 被当成了弧度。从度转弧度的标准写法是(* ang (/ pi 180.0))或者写成(/ (* ang pi) 180.0)(setq ang 30) ; 30 度 (setq rad (/ (* ang pi) 180.0)) ; 转弧度 (setq y (sin rad)) ; 0.5 (setq x (cos rad)) ; 0.866025 (setq t (atan 1.0)) ; 0.785398pi/4atan有个更实用的变体(atan y x)可以直接返回点相对于原点的方位角范围是 -pi 到 pi比(angle (0 0) (list x y))少一步构造列表。exp、log、expt用的频率不高但做拟合计算或指数衰减时能顶上。手册里还有个pi常数约 3.1415926注意它不用括号直接写pi。2.2 比较、位运算与判断函数、equal、eq 的区别是重点逻辑判断函数里、eq、equal三者最容易混。手册原文给的解释很简练适用于数值和字符串eq是“实际相同”equal是“内容相同”。实际项目里判断字符串用最直接判断列表内容用equal而eq是用来判断两个变量是否指向同一个列表对象(setq s1 abc) (setq s2 abc) ( s1 s2) ; T字符串内容相等 (equal s1 s2) ; T内容相同 (setq l1 (list 1 2)) (setq l2 (list 1 2)) (eq l1 l2) ; nil两个列表不是同一个对象 (equal l1 l2) ; T但内容完全相同 (equal 3.0 3.0000001 0.001) ; T带差量比较浮点误差的后悔药equal的第三个参数是差量这是处理浮点比较的唯一正经办法。比如计算两个点是否重合( (distance p1 p2) 0)极大概率会得到 nil因为浮点误差正确写法是(equal (distance p1 p2) 0.0 1e-6)。我一般会把这种判断封装成一个工具函数避免每次手写容差。、、、的用法和一样都可以接受多个参数做链式比较( 1 2 3)返回 T。位运算里的~是按位取反boole是低位布尔运算这两个在工程图里少用但做图元状态位判断时会遇到。and、or是短路逻辑(and (setq a (getvar CMDECHO)) a)这类写法能在一个表达式里同时完成赋值和判断。if和cond是后面写流程控制的地基。这里先埋一个点AutoLISP 里只有nil是假其他任何值包括 0 和空字符串都是真。这跟 C 语言完全不同新手写(if ( n 0) ...)没问题但如果写(if n ...)想表达“n 不为零”就翻车了因为 n 等于 0 时 0 也是“真”。3. 列表与字符串处理AutoLISP 数据交换的“主干道”AutoLISP 之所以叫 LISP就是因为一切数据都是列表。点坐标是列表对象信息表是列表选择集内部结构也是列表。这一章把列表的构建、访问、批量处理讲透再把字符串和文件读写接上程序的数据进出就闭环了。3.1 列表构建与访问car、cdr、cons、append 的组合car取第一个元素cdr去掉第一个元素后返回剩下的列表cadr是car和cdr的组合写法取第二个元素。这三个函数看着简单但在点坐标处理里是标配(setq pt (getpoint \n指定点: )) ; 返回 (x y z)比如 (5.0 3.0 0.0) (setq x (car pt)) ; 5.0 (setq y (cadr pt)) ; 3.0 (setq z (caddr pt)) ; 0.0 (setq pt2 (list x y)) ; (5.0 3.0)去掉 Z 坐标注意getpoint返回的是三维点表如果你要传给只接受二维点的函数最好用list重新构造。cons是“构造列表”它把新元素放到列表头部(cons 1 (2 3))返回(1 2 3)。append是把多个列表拼接成一个(append (1 2) (3 4))返回(1 2 3 4)。cons在 AutoLISP 里还有一个特殊用途构造关联表的键值对。比如图层信息、对象扩展数据都是用(cons 键 值)的格式存放的(setq alist (list (cons NAME BRACE) (cons THK 16))) (assoc NAME alist) ; 返回 (NAME . BRACE) (cdr (assoc THK alist)) ; 16取出键对应的值assoc按关键字查找cdr取出值。取对象图元信息时(cdr (assoc 0 (entget en)))能拿到对象的类型字符串这就是后面第 4 章要频繁用的套路。reverse翻转列表、subst替换元素、nth按索引取值是辅助角色但subst在改图元组码时很好用比如把半径组码 40 的值替换掉。3.2 批量处理foreach、mapcar 与 lambda 的组合处理一批坐标点或一批对象时foreach和mapcar是两种思考方式。foreach是“对每个元素做同一件事”不关心返回值mapcar是“对每个元素做变换并收集结果”返回新列表(setq pts ((0 0) (1 1) (2 2) (3 3))) (mapcar (lambda (p) (distance (0 0) p)) pts) ; 返回 (0.0 1.41421 2.82843 4.24264) (foreach p pts (princ p) (princ \n) )lambda在这里是匿名函数(lambda (p) ...)里那个引号不能省。mapcar还有个用法是配合apply做聚合计算(apply (mapcar car pts))能求出所有 X 坐标之和。apply把函数作用到列表上可以接受多个参数这个组合在统计坐标范围时非常顺手。批量处理的核心思想是“先把数据组织成列表再用 mapcar/foreach 一次性处理”而不是像其他语言那样写索引循环。AutoLISP 的repeat和while更接近底层操作但foreach的可读性明显更好。代码审查时看到foreach基本能立刻明白意图而while加索引变量还得数几行才能反应过来。3.3 字符串、文件与转换函数把外部数据接进来字符串函数在生产工具里天天用。strcat拼接、substr截取、strlen取长度、strcase转大小写、wcmatch做通配符匹配。wcmatch支持*、?、#等模式判断文件名或图层名是否匹配前缀比substr更简洁(setq fn BRACE-01.dwg) (wcmatch fn BRACE*) ; T (wcmatch fn ???-*.dwg) ; Trtos和angtos是经常被忽略的“数据格式化”函数。把实数转成字符串时不指定模式会采用当前图形的线性单位设置导致在不同图纸上跑出不同结果。我一般会显式指定模式模式含义示例数值 12.51科学计数1.2500E012小数12.503工程英尺-英寸1-0.504建筑英尺-英寸分数1-0 1/25分数12 1/2写标注类工具时如果rtos不指定模式标注文字会跟着图纸单位设置变这在批量出图时很容易翻车。angtos同理角度转字符串时要显式指定度和精度。文件读写方面open配合read-line、write-line能读写文本文件最常见的场景是读坐标文件批量画点。注意open的第二个参数是模式字符串r 读、w 写、a 追加(setq f (open D:/pts.txt r)) ; 文件不存在时返回 nil (while (setq line (read-line f)) ; 读到文件尾返回 nil循环结束 (setq data (read (strcat ( line )))) ; 把 10,20 变成可处理的数据 (princ data) (princ \n) ) (close f) ; 用完必须关这段代码里(read (strcat ( line )))是把文本行包上括号再解析成列表常见做法能省去手工 split 的麻烦。read函数解析字符串为 LISP 数据但要求字符串本身是合法的 LISP 表达式所以要先拼一对括号。文件路径建议用正斜杠反斜杠要写成双反斜杠转义这是 Windows 路径的老坑。4. 几何计算与对象操作把坐标和选择集变成批量改图的能力前面两章处理的是“数值”和“数据”从这一章开始接触真正的图形。几何函数负责计算对象函数负责读写图元选择集负责批量圈选三样组合起来才能写出能用的工程工具。4.1 几何函数配合angle、distance、polar、inters、osnapangle返回两点连线与 X 轴的夹角单位是弧度distance返回两点距离polar从基点按角度和距离推算新点。这三个函数配合能解决大部分几何定位问题。比如求线段中点(setq p1 (getpoint \n第一点: )) (setq p2 (getpoint \n第二点: )) (setq d (distance p1 p2)) ; 线段长度 (setq a (angle p1 p2)) ; 线段方位角弧度 (setq mid (polar p1 a (/ d 2))) ; 从 p1 沿方位角走一半距离polar的第三参数必须是距离第二参数必须是弧度。如果手头是角度得先转换。inters求两条直线交点它有四个点参数和一个模式参数模式为 nil 时只返回实际相交的点模式为 T 时即使延长线相交也返回交点。判断线段是否真的相交就用模式 nil判断延长线交点用 T。osnap按捕捉模式取点比如(osnap pt end)返回 pt 附近端点的坐标。这个函数在模拟“鼠标捕捉”场景里很有用但要注意它依赖当前图形里的对象如果 pt 附近没有符合条件的对象返回 nil。4.2 对象与选择集entget、entmod、ssget 的过滤用法AutoLISP 操作对象的基本流程是entsel或ssget拿到对象名entget取出对象信息表修改表里的组码值再用entmod写回。组码是 AutoCAD 的“黑匣子”0 是对象类型10 是起点/插入点40 是半径/高度8 是图层名。用assoc和cdr就能读出来(setq en (car (entsel \n选择圆: ))) ; entsel 返回 (对象名 . 选点坐标) (setq ed (entget en)) ; 对象信息表 (setq r (cdr (assoc 40 ed))) ; 半径 (setq layer (cdr (assoc 8 ed))) ; 图层名ssget批量选择时可以用过滤列表这是选择集最强大的地方。下面的代码选出当前空间所有半径为 50 的圆(setq ss (ssget ((0 . CIRCLE) (40 . 50.0)))) (setq n (sslength ss)) ; 选择集中对象数量 (setq i 0) (repeat n (setq en (ssname ss i)) ; 按索引取对象名 (setq ed (entget en)) ; 这里对每个圆做处理 (setq i (1 i)) )ssget的过滤列表是关键。(0 . CIRCLE)按对象类型过滤(40 . 50.0)按半径组码过滤。注意组码值必须和图中存储的类型一致半径是实数就写50.0写成50可能过滤不出来。选择集下落不明的坑在下一章专门讲。entmod修改对象信息表后屏幕上不一定立刻刷新。一般图元entmod后会自动更新但复杂对象或插入块里的子对象要补一句entupd才能重绘。这是“改了没反应”的常见原因。4.3 示例批量修改文字高度把前面这些函数串起来写一个实用工具选中一批文字统一把字高改成 3.5。整套逻辑覆盖选择集遍历、组码读取、组码修改、对象更新(defun c:TH (/ ss i en ed old new) (setq ss (ssget ((0 . TEXT)))) ; 只选 TEXT 对象 (if ss (progn (setq i 0) (repeat (sslength ss) (setq en (ssname ss i)) (setq ed (entget en)) (setq old (cdr (assoc 40 ed))) ; 40 组码是文字高度 (setq new 3.5) (setq ed (subst (cons 40 new) (assoc 40 ed) ed)) ; 替换高度 (entmod ed) ; 写回图形 (entupd en) ; 强制刷新 (setq i (1 i)) ) ) ) (princ) )这里subst替换组码时要同时传入新点和旧点(subst (cons 40 new) (assoc 40 ed) ed)意思是“把表里第一个出现的旧组码换成新组码”。progn把多条表达式包成一组因为if只能跟一个表达式。(princ)放在函数末尾是为了静默退出不然函数返回最后一个表达式的值命令区会多一行数字或列表。这个小习惯能让工具看起来更专业。5. 常见问题排查与函数编写五个高频踩坑场景的现场复盘写 AutoLISP 最难受的不是语法难而是“明明照着手册写了就是不干活”。这一章复盘五个高频翻车现场每条都按“现象 → 原因 → 解决”的顺序写都是实际项目里会碰到的真问题。5.1 加载即报错括号不配平与中文符号现象(load tool.lsp)后命令行提示malformed list on input或者“无效的选项关键字”文件一上来就挂了。原因最常见是括号不配平特别是长函数多处if嵌套时少写一个右括号是常态其次是从网页复制的代码混进了全角括号、全角引号LISP 解析器不认。解决编辑器里用括号匹配功能把光标放在左括号上看有没有对应的右括号高亮文件里搜一下有没有中文括号和中文引号。我的习惯是每一层嵌套都缩进对齐函数末尾的括号单独占一行检查时一眼能数清层数。5.2 返回值 nil函数没输出到底哪里出了问题现象调用自定义函数后命令区只有nil什么都没发生。原因nil不一定是错误。while循环结束时返回 nilprinc返回 nilsetq的返回值是被赋的值而不是 nil但如果函数最后一个表达式是(princ)整个函数就返回 nil这是正常的静默退出。真正的问题是if 条件判断错了分支或者函数里某个setq赋值给了未被正确引用的局部变量。解决在函数体里临时加(princ ...)打印中间变量看是哪个环节断了检查if的条件AutoLISP 里 0 和空字符串都是“真”只有nil是“假”用(if (setq x ...))时要确认 x 确实被赋了非 nil 值。5.3 坐标点不对UCS 与 WCS 的转换现象用getpoint取的点画出来的线位置明显不对或者跟对象信息表里记录的坐标对不上。原因getpoint返回的是当前 UCS 下的坐标而entget得到的图元几何数据在 WCS 或 OCS 里。坐标系不一致计算就全错。解决统一用trans做转换。(trans pt 1 0)把点从 UCS 转到 WCS(trans pt 0 1)转回来(setq pt (getpoint \n指定点: )) (setq pt_wcs (trans pt 1 0)) ; UCS 坐标转 WCS (setq pt_ucs (trans pt_wcs 0 1)) ; WCS 坐标转回 UCStrans的第三个参数如果是整数 0、1、2分别对应 WCS、UCS、显示坐标系。很多“点没画对”的玄学最后都出在这。我的习惯是从getpoint拿到的点立刻转成 WCS 再参与计算避免后面跟图元数据比较时空对空。5.4 entmod 不生效组码值类型与刷新顺序现象entmod执行了没有任何报错但图上的对象就是没变。原因有两类。第一类组码值类型不对比如半径组码 40 存的是实数你给个整数 50有的版本能接受有的版本直接忽略。第二类修改的是块表记录或复杂对象entmod之后需要regen或entupd才能看到效果。解决修改前先(cdr (assoc 40 ed))看数据类型修改后用(entupd en)刷新对象如果还没反应就(command regen)。另外entmod只能修改图元数据不能新增对象新增要entmake这两个经常混。5.5 加载 ARX 或 LSP 失败版本、路径与依赖现象(arxload some.arx)报“无法加载”或(load tool.lsp)提示找不到文件但文件明明在。原因ARX 程序跟 AutoCAD 版本强绑定一个版本编译的 ARX 换到另一个版本就加载不了LSP 文件路径里有中文或空格某些旧版本处理不了还有一类是 LSP 文件开头写了中文编码注释加载时编码不兼容。解决先用(findfile some.arx)确认路径再用arxload路径尽量全英文LSP 文件用 ANSI 编码保存或者干脆不用中文注释改用英文注释。load的第二个参数可以写加载失败时的提示字符串比如(load tool.lsp 加载失败检查文件路径)这样至少知道失败原因而不是闷头报错。6. 把手册变成工具箱用 defun 组织自己的 LISP 函数库手册翻完最后要落在一个习惯上按类别拆分函数用defun封装成可复用的工具而不是把几百个函数塞进一个文件。我会按功能建若干文件math.lsp放坐标转换、角度处理list.lsp放列表工具函数io.lsp放文件读写geom.lsp放几何计算。每个文件里只放defun定义的函数不写执行语句主程序里用(load geom.lsp)按需加载。这样做的好处是一个函数出问题只影响一个文件排查范围小很多。写命令类函数时我强制自己套一个固定模板这个模板能挡住一半以上的坑(defun c:TT (/ old p1 p2) (setq old (getvar cmdecho)) ; 保存系统变量 (setvar cmdecho 0) ; 关闭命令回显 (setq p1 (getpoint \n第一点: )) (setq p2 (getpoint \n第二点: )) (command line p1 p2 ) ; 调 AutoCAD 命令画线 (setvar cmdecho old) ; 恢复系统变量 (princ) ; 静默退出 )模板的三个要点函数名后的/后面声明所有局部变量避免污染全局getvar保存被修改的系统变量结束时恢复不然用户的cmdecho设置被改掉后面的操作会变得很吵结尾的(princ)保证函数不返回多余值。如果是更复杂的命令还要在*error*里也恢复系统变量防止程序中断后变量停留在被修改状态。从那以后我每次写工具函数都强制走一遍“声明局部变量、保存系统变量、恢复、静默退出”这个流程出问题的概率低了很多。希望帮到你。本文还有配套的精品资源点击获取