jh1215218 发表于 2025-5-6 20:31:59

多条件查找和多内容一一 替换插件

最近用AI写了一个lisp插件。支持多条件对应多内容一一替换(保留查找条件不变)


目前发现一个问题,就是输入条件内容和替换内容 对于输入长度有限制255字符(我想查找上千个内容,然后替换上千条)。
特放出代码看看有没有解决办法。

(defun c:ddth (/ *error* findList replaceList replacePairs selSet entData txtContent mode regex originalContent
                  dcl_id find_str replace_str last_find last_replace tmpdcl)
;; 错误处理函数
(defun *error* (msg)
    (if (and regex (eq 'VLA-OBJECT (type regex)))
      (vlax-release-object regex)
    )
    (if tmpdcl (vl-file-delete tmpdcl))
    (if dcl_id (unload_dialog dcl_id))
    (if (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*"))
      (princ (strcat "\n错误: " msg))
    )
    (princ)
)

;; ========== 增强型字符串分割函数 ==========
(defun splitString (str delim / pos result token)
    (cond
      ((or (null str) (= str "")) '()); 处理空输入情况
      (T
      (setq result '())
      (while (setq pos (vl-string-search delim str))
          (setq token (substr str 1 pos))
          (if (/= token ""); 跳过空项
            (setq result (cons (vl-string-trim " " token) result))
          )
          (setq str (substr str (+ pos 1 (strlen delim))))
      )
      (if (/= str ""); 添加最后一段
          (setq result (cons (vl-string-trim " " str) result))
      )
      (reverse result)
      )
    )
)

;; ========== 增强型字符串替换 ==========
(defun vl-replace-all (text searchStr replaceStr / len newText pos)
    (setq len (strlen searchStr)
          newText ""
          pos 0)
    (while (<= (+ pos len) (strlen text))
      (if (and
            (= (substr text (1+ pos) len) searchStr)
            (or (= pos 0) (wcmatch (substr text pos 1) "[~0-9A-Za-Z]")) ; 前导边界
            (or (= (+ pos len) (strlen text))
                (wcmatch (substr text (+ pos len 1) 1) "[~0-9A-Za-Z]")) ; 后继边界
          )
      (setq newText (strcat newText searchStr " → " replaceStr) ; 显示查找和替换内容
            pos (+ pos len))
      (setq newText (strcat newText (substr text (1+ pos) 1))
            pos (1+ pos))
      )
    )
    (strcat newText (substr text (1+ pos)))
)

;; ========== 正则表达式替换函数 ==========
(defun regex-replace (text pattern replacement)
    (setq regex (vlax-create-object "vbscript.regexp"))
    (vlax-put-property regex 'Global 1)
    (vlax-put-property regex 'Pattern pattern)
    (setq result (vlax-invoke regex 'Replace text replacement))
    (vlax-release-object regex)
    result
)
;; 主程序
(vl-load-com)

;; 读取上次输入
(setq last_find (vl-registry-read "HKEY_CURRENT_USER\\Software\\DDTH" "LastFind"))
(setq last_replace (vl-registry-read "HKEY_CURRENT_USER\\Software\\DDTH" "LastReplace"))

;; 创建临时DCL文件
(setq tmpdcl (vl-filename-mktemp "ddth.dcl"))
(setq dclfile (open tmpdcl "w"))
(write-line
"ddth_dialog : dialog {
label = \"批量文本替换\";
: row {
    : boxed_column {
      label = \"查找内容(逗号分隔)\";
      : edit_box {
      key = \"find\";
      width = 50;
      allow_accept = true;
      }
    }
    : boxed_column {
      label = \"替换内容(逗号分隔)\";
      : edit_box {
      key = \"replace\";
      width = 50;
      allow_accept = true;
      }
    }
}
spacer;
: row {
    fixed_width = true;
    alignment = centered;
    : button {
      key = \"accept\";
      label = \"确定\";
      is_default = true;
    }
    : button {
      key = \"cancel\";
      label = \"取消\";
      is_cancel = true;
    }
}
}" dclfile)
(close dclfile)

;; 加载对话框
(setq dcl_id (load_dialog tmpdcl))
(if (not (new_dialog "ddth_dialog" dcl_id))
    (progn (alert "无法加载对话框!") (exit))
)

;; 初始化对话框
(set_tile "find" (if last_find last_find ""))
(set_tile "replace" (if last_replace last_replace ""))

;; 设置动作
(action_tile "accept" "(setq find_str (get_tile \"find\") replace_str (get_tile \"replace\")) (done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")

;; 显示对话框
(setq dcl_res (start_dialog))
(unload_dialog dcl_id)
(vl-file-delete tmpdcl)
(setq tmpdcl nil)

(if (= dcl_res 0)
    (exit)
    (progn
      ;; 保存输入到注册表
      (vl-registry-write "HKEY_CURRENT_USER\\Software\\DDTH" "LastFind" find_str)
      (vl-registry-write "HKEY_CURRENT_USER\\Software\\DDTH" "LastReplace" replace_str)

      ;; 处理输入内容
      (setq findList (splitString find_str ","))
      (setq replaceList (splitString replace_str ","))
      
      (if (/= (length findList) (length replaceList))
      (progn
          (alert "错误: 查找项与替换项数量不一致!")
          (exit)
      )
      )
    )
)

;; 创建替换对集合
(setq replacePairs (mapcar 'cons findList replaceList))

;; 对象选择
(prompt "\n请选择要处理的TEXT/MTEXT对象: ")
(setq selSet (ssget '((0 . "TEXT,MTEXT"))))

;; 替换执行
(if selSet
    (progn
      (initget "Wcmatch Regex")
      (setq mode (cond ((getkword "\n选择匹配模式 <W>: ")) ("Wcmatch")))
      
      (setq i 0
            totalReplacements 0)
      (repeat (sslength selSet)
      (setq entData (entget (ssname selSet i))
            txtContent (cdr (assoc 1 entData))
            originalContent txtContent)
      
         ;; 根据模式选择替换算法
      (foreach pair replacePairs
          (setq txtContent
            (if (eq mode "Regex")
            (regex-replace txtContent
                            (strcat "\\b" (vl-string-translate "*?." "\\*\\?\\." (car pair)) "\\b")
                            (strcat (car pair) " → " (cdr pair))) ; 显示查找和替换内容
            (vl-replace-all txtContent (car pair) (cdr pair))
            )
          )
      )
      
      ;; 更新实体
      (if (not (equal txtContent originalContent))
          (progn
            (entmod (subst (cons 1 txtContent) (assoc 1 entData) entData))
            (setq totalReplacements (1+ totalReplacements))
          )
      )
      (setq i (1+ i))
      )
      (princ (strcat "\n处理了 " (itoa i) " 个对象,成功替换 " (itoa totalReplacements) " 处文本"))
    )
    (princ "\n未选择有效对象")
)
(princ)
)

(princ "\n文本批量替换命令已加载,输入 ddth 启动。")

你有种再说一遍 发表于 2025-5-6 20:42:36

字符串限制罢了,我告诉一个最简单的方法,换到C#.
不简单的方法是:写入一个文件内,再读取它,就可以破除字符串数量限制.

kozmosovia 发表于 2025-5-6 21:05:11

255个字符都够表达一段话了,这是要替换字符还是重写文章?
还上千条,一条255个字符就得至少25W字符,12W汉字,是用CAD写书呢?

tanxindong 发表于 2025-5-7 08:17:04

收下了,备用

197761308 发表于 2025-5-7 15:27:46

强,太强了,实在是太强了!!!

paulpipi 发表于 2025-5-7 16:36:33

收藏备用,感谢分享

香远益清 发表于 2025-5-8 09:25:34

现在这类插件不需要了,高版本CAD2026自带图形查询替换功能,命令mea完美解决了这类插件的功能!

holypower2011 发表于 2025-5-8 11:42:05

香远益清 发表于 2025-5-8 09:25
现在这类插件不需要了,高版本CAD2026自带图形查询替换功能,命令mea完美解决了这类插件的功能!

我试了2026没mea这个命令呢?

香远益清 发表于 2025-5-9 15:27:43

本帖最后由 香远益清 于 2025-5-9 15:29 编辑

holypower2011 发表于 2025-5-8 11:42
我试了2026没mea这个命令呢?
对不起,说错了,是bse命令{:1_1:}而mea是动态显示尺寸和角度命令。抱歉,一时记混了。

guosheyang 发表于 2025-5-9 17:38:50

必须是英文逗号   最好 可以将中文逗号直接转成英文逗号替换就直接替换 觉得没必要搞个箭头:lol
页: [1] 2
查看完整版本: 多条件查找和多内容一一 替换插件