• [ Skill ] load 函数优化,识别相对路径


    https://www.cnblogs.com/yeungchie/

    cds.lib 文件中定义库的路径,为了规范管理库的定义,经常这样做:

    复制代码
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    text
    $ tree . |-- cds.lib ------------------- cat --> 1| INCLUDE ./common/cds.lib `-- common |-- cds.lib --------------- cat --> 1| INCLUDE ./project/cds.lib | 2| INCLUDE ./project/cds.lib |-- project | |-- cds.lib ----------- cat --> 1| INCLUDE ./layout/cds.lib | | 2| INCLUDE ./sch/cds.lib | | 3| 略 ... | |-- layout | | `-- cds.lib ------- cat --> 1| DEFINE layout_lib1 ./layout_lib1 | | 2| DEFINE layout_lib2 ./layout_lib2 | | 3| 略略 ... | |-- sch | | `-- cds.lib ------- cat --> 1| 略略略 ... | `-- 略略略略 ... `-- 略略略略略 ...

    可以看到,对于 cds.lib 文件来说,INCLDUE / DEFINE 都可以使用相对路径。
    而在 Skill 中使用 load() / loadi() 函数却不能支持相对路径:

    *Error* load: can't access file - "./dir/test.il"
    *Error* load: error while loading file - "/home/yeung/tmp/load.il" at line 1

    在上一篇随笔 文件读写 & IO 句柄 整理的内容中,发现内置的句柄 piport 可以获取当前文件的路径这一特性,于是有了这一篇。

    几个函数

    __FILE__

    在 Perl 中 __FILE__ 用来获取当前文件的路径,这里模仿一个。

    复制代码
    • 1
    • 2
    • 3
    lisp
    procedure(__FILE__() get_filename(piport) ); __FILE__
    • 运行:

      复制代码
      • 1
      • 2
      lisp
      printf("Current path: %s\n" (__FILE__)) ; Current path: /home/yeung/tmp/load.il

    __DIR__

    正则处理,从 __FILE__ 函数结果中提取父目录的路径。
    需要注意的是,如果是在 CIW 中执行 __FILE__ 函数,它的返回值会是 *ciwInPort*,这种情况直接用 getWorkingDir() 作为 __DIR__ 函数的返回值。

    复制代码
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    lisp
    procedure(__DIR__(\@optional path((__FILE__)) "t") if(pcreMatchp("^\\*.+\\*$" path) getWorkingDir() pcreReplace(pcreCompile("(?<=/)[^/]+/*$") path "" 0) ) ); __DIR__
    • 运行:

      复制代码
      • 1
      • 2
      lisp
      printf("Current directory: %s\n" (__DIR__)) ; Current directory: /home/yeung/tmp/

    ycReadRelPath

    这个函数用来将 相对路径 转为 绝对路径
    当输入路径 path 为 ~ 或者 / 开头时,说明已经是绝对路径了,这种情况直接原封不动返回。

    复制代码
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    lisp
    procedure(ycReadRelPath(\@optional file("") "t") let((path) path = if(pcreMatchp("^[~/]" file) file sprintf(nil "%s/%s" (__DIR__) file) ) simplifyFilename(path t) ); let ); ycReadRelPath
    • 运行:

      复制代码
      • 1
      • 2
      lisp
      printf("Target path: %s\n" ycReadRelPath("./init/load.il")) ; Target path: /home/yeung/tmp/dir/test.il

    ycLoad

    优化 load 函数。
    预留一个 ignore 参数用来优化 loadi 函数。

    复制代码
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    lisp
    procedure(ycLoad(file \@optional ignore "tg") let((path) path = ycReadRelPath(file) unless(isFile(path) error("ycLoad: not a valid file - %A" path) ) unless(isReadable(path) error("ycLoad: can't access file - %A" path) ) if(ignore loadi(path) load(path)) ) ); ycLoad

    ycLoadi

    优化 loadi 函数。
    同样可以忽略 load 过程中遇到的错误,打印错误消息,然后继续 load 。

    复制代码
    • 1
    • 2
    • 3
    lisp
    procedure(ycLoadi(file "t") ycLoad(file t) ); ycLoadi

    效果

    • 以前 load

      复制代码
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      lisp
      let((home wind sync) home = "/home/yeung/script/skill/tools/" wind = list("hiForm.il" "windCtrl.il") sync = list("syncView.il" "support3rd.il") foreach(x wind load(strcat(home "src/wind/" x)) ) foreach(x sync load(strcat(home "/src/sync/" x)) ) ); let

      非常啰嗦。
      其次如果父文件夹改了名,或者移动了位置,还得一个个文件打开检查路径并修改,还要增加无意义的版本。
      copy 给别人也不能傻瓜式操作,直接 load 报个错:

      *Error* load: can't access
      " 唉 你 这 脚 本 有 问 题 啊 ? "
    • 现在 load

      复制代码
      • 1
      • 2
      • 3
      • 4
      • 5
      lisp
      ycLoad("src/wind/hiForm.il") ycLoad("src/wind/windCtrl.il") ycLoad("src/sync/syncView.il") ycLoad("src/sync/support3rd.il") ; END 这里为什么空一行,在 FAQ 会解释

      "优雅地" load 完所有文件。


    继续优化可以再识别 Shell 环境中的变量。

    FAQ

    1. 发现一个稳定性问题,初步判断可能是 Skill 本身的 bug

      复制代码
      • 1
      lisp
      ycLoad("src/sync/support3rd.il")

      上面这几句加载后可能会出现找不到文件的报错,语句本身是没有问题的。
      自己测试发现,piport 可能会被赋予到 “错误” 的值。
      猜测原因在于,读取完最后一句 ycLoad 之后,当前的文件已经没有再需要读取的内容了,又因为某些问题存在一定的延迟,此时指针可能已经回到了上一个文件中,所以接着 get_filename(piport) 获取到了错误的路径。

      这个现象是我的脚本文件位于远程存储挂载在本地的路径的时候发现的,复现率极高。

      解决办法:ycLoad 不要位于最后一行

      复制代码
      • 1
      • 2
      lisp
      ycLoad("src/sync/support3rd.il") ; 特意空一行
  • 相关阅读:
    Yakit工具篇:专项漏洞检测的配置和使用
    1012 The Best Rank
    1、40个linux高效运维命令总结
    Java多线程开发CompletableFuture的应用
    linux(1.nginx基础 && 2.使用Nginx负载均衡及动静分离)
    项目之用ARM串口关联巴法云进行推送或者订阅
    VMware Workstation 与 Device/Credential Guard 不兼容 解决办法
    GBASE南大通用签约广东省某城市商业银行
    使用wxPython和PyMuPDF合并PDF文档并自动复制到剪贴板
    高并发场景中,数据库都有哪些优化手段?不会还有人不知道吧
  • 原文地址:https://www.cnblogs.com/yeungchie/p/15999427.html