V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lolizeppelin
V2EX  ›  程序员

求个完美的文件夹校验正则

  •  
  •   lolizeppelin · 2020-02-16 16:18:17 +08:00 · 4782 次点击
    这是一个创建于 1750 天前的主题,其中的信息可能已经有所发展或是发生改变。
    if WINDOWS:
        if IS_WINDOWS_LINUX_SUBSYSTEM:
            DIRECTORY_REGEX = '^/[a-z](/([0-9a-z_.]+?[0-9a-z_.-]*){1,}){0,}$'
        else:
            DIRECTORY_REGEX = '^[a-z]:(\\\\([0-9a-z_.]+?[0-9a-z_.-]*){1,}){0,}$'
    else:
        DIRECTORY_REGEX = '(/([0-9a-zA-Z_.]+?[0-9a-zA-Z_.-]*){1,}){1,}$'
    

    上面的基本校验没问题...

    但是没办法避免相对路径比如../ 做法是禁止出现斜杠后有../和./ 我以前写过一个类似的文件名校验的

    PATHPATTERN = r'^[A-Za-z0-9]+?(?!.*?/[\.]{1,}/)([A-Za-z0-9\.\-_/])+?[A-Za-z0-9]+?$'
    

    然后我现在看不懂了...求个最优的写法 orz

    19 条回复    2020-02-18 20:05:50 +08:00
    jaynos
        1
    jaynos  
       2020-02-16 16:27:47 +08:00
    这是在校验是否有权限访问某个目录么?换个思路,可以直接拿着这个路径取得绝对路径,这样判断就简单了。
    lolizeppelin
        2
    lolizeppelin  
    OP
       2020-02-16 16:31:39 +08:00
    @jaynos
    配置文件模块只支持正则校验, 用访问目录校验就得在具体业务代码里做了

    就是希望在配置文件模块里通过正则做完校验,这样更通用一点
    imn1
        3
    imn1  
       2020-02-16 17:01:54 +08:00
    没有完美的,如果不是实例检验的话,就是一个字符串
    测一下有没有非法字符,有没有路径符,仅此而已
    zhijiansha
        4
    zhijiansha  
       2020-02-16 18:05:02 +08:00
    (?!.*?\.+/) 禁止路径中出现../ ./,可以加在你上面的那些正则表达式的前面
    ysc3839
        5
    ysc3839  
       2020-02-16 18:25:52 +08:00 via Android
    用 lexically normalize 可以去掉 ../ 和 ./ 这种相对路径。
    AX5N
        6
    AX5N  
       2020-02-16 20:20:43 +08:00
    你的意思是只能根据一段字串符来判断这段字串符是否是目录? 我觉得做不到,比如文件夹也可以起名为“a.exe”
    nightwitch
        7
    nightwitch  
       2020-02-16 20:42:24 +08:00
    应该放到业务代码里去校验。采用文本的方法去匹配就像打地鼠一样,总能出现匹配不上的情况。
    azh7138m
        8
    azh7138m  
       2020-02-16 20:44:47 +08:00
    提供一个 case
    '/😀'
    再来一个
    '/ b' (b 前面有个空格)
    raysonx
        9
    raysonx  
       2020-02-16 20:54:31 +08:00 via iPad
    Linux 系统下只有两个字符不能用作文件名,一个是路径分割符 /,另一个是 NUL (\0 )。
    MrUser
        10
    MrUser  
       2020-02-16 22:20:55 +08:00
    只能通过判断是否包含有路径禁止使用的符号来实现了吧?
    路径中可以有 .. 比如下图:
    https://s2.ax1x.com/2020/02/16/39w2B6.png
    Buges
        11
    Buges  
       2020-02-16 22:31:10 +08:00 via Android
    你应该仿照系统处理路径的思路去处理。
    lolizeppelin
        12
    lolizeppelin  
    OP
       2020-02-17 12:07:54 +08:00
    @zhijiansha
    谢谢...就是这个,比我之前处理文件名的那个写法好

    我发现我之前也用了环视处理文件名,但是现在已经看不懂了 2333
    ceyes
        13
    ceyes  
       2020-02-17 15:41:47 +08:00
    X-Y Problem 又叫“过早下结论”:提问者其实并不非常清楚想要解决的 X 问题,他猜测用 Y 可以搞定,于是他问大家如何实现 Y。

    Ref: https://coolshell.cn/articles/10804.html


    所以楼主真正想解决的是什么问题呢?
    no1xsyzy
        14
    no1xsyzy  
       2020-02-17 15:51:44 +08:00
    第一,有什么阻止相对路径的必要?如果哪个程序不让我用相对路径我多半会骂娘
    第二,阻止相对路径建议添加反判断 r"/\.\./" 和 r"/\./",正反判断组合能够让正则效率和可读性同时提升不少。
    第三,不行就找 r"(/[^.].*|.[^.].*|\.\..+)+/?" 找出“第一个字符不是 . 的”、“第二个字符不是 . 的”、“前两个字符都是 . 但还有更多内容的”
    括号内对应 if 就是:
    if len(s)>=1 and s[0] != ".": return True
    if len(s)>=2 and s[1] != ".": return True
    if len(s)>=3: return True
    lolizeppelin
        15
    lolizeppelin  
    OP
       2020-02-17 18:16:17 +08:00
    @ceyes

    1.配置文件模块只支持字符串做正字校验
    2.尽量在配置模块中避免用户输入相对路径(并尽量保证路径字符串正确)
    这样应用可以直接拼写路径而不用做一次转换

    通过非正则方式校验简单.但是要在配置文件模块以外做
    用正则就是为了在配置文件模块部分校验字符串而不是让后面应用做

    oslo config 的配置提供了多种 opt,如果需要可以自己创建文件夹类型 opt 以及对应校验
    但是这样需要载入自己的 class,所以才直接用了 StringOpt 加正则来做

    https://github.com/openstack/oslo.config/blob/master/oslo_config/cfg.py


    @no1xsyzy
    1.配置文件里路径绝对路径安全避免问题,又不是命令行工具次次要你输一长串
    2.IDE 里用 r 有警告提示看着烦
    3.oslo config 不支持直接传入校验函数,需要集成重写,原因上面也说了
    no1xsyzy
        16
    no1xsyzy  
       2020-02-17 18:42:58 +08:00
    @lolizeppelin
    1. 配置文件要求更高,我认为包括 ~ 都需要正确响应。
    2. 这是什么鬼 IDE 用 r 有警告的?还是 lint 配置没配置好?(注意:大部分语言的大部分 linter 的默认配置是垃圾,比如 pylint 默认配置不符合 pep-20,请复制别人或者大公司的现成配置,自己配能有多个项目用得上也行)另外,我认为所有的正则都**必须**加 r,无论其中是否用到反斜杠,本来 r-string 语法一定程度上就是为了正则才加的,并且也是一个显著视觉标记,最重要的是,VS Code 里加了 r 的话代码高亮也会按正则来。
    3. 我是在用 if 描述 r"(/[^.].*|.[^.].*|\.\..+)+/?"。你可能不知道:正则表达式的实质是 if 语句和一种非无限递归的混合;
    4. 我不认为有必要在配置文件模块中确认配置无误,尤其在此配置业务层还会再验证一遍的情况下,唯一的例外是需要错误信息前置。
    5. tips: 看不懂自己曾经写的正则的问题可以靠 re.VERBOSE 解决
    no1xsyzy
        17
    no1xsyzy  
       2020-02-17 19:23:23 +08:00
    lolizeppelin
        18
    lolizeppelin  
    OP
       2020-02-17 21:34:47 +08:00
    配置文件是字符串.没必要在配置文件部分确保他表达的对象正确
    比如说一个动态加载的 backend, 你只要在配置里确保这个 backend 的字符串符合你自己定义的规范就可以
    而不需要确保这个 backend 确实存在

    同样我的 path 是否正确配置文件层面我只要确定 path 的字符串的正确性符合我的规范就是

    因为配置文件代码最先执行,当然会前置错误信息....否则报错得到具体 api 调用的时候了

    需求这个正则是因为路径最后要和 url 资源路径对应
    配置文件层我就可以通过正则避免相对路径导致可能的越界
    这样业务层就不用再检查路径问题了,只要处理 io 错误而不用每次都要调用一次转绝对路径函数


    正则这个 if 我确实不知道,因为不是很喜欢写正则,今天会了过两天就忘记了,脑壳痛
    no1xsyzy
        19
    no1xsyzy  
       2020-02-18 20:05:50 +08:00
    @lolizeppelin
    我看了下 oslo.config 好像没有前置错误信息(注意连错误信息内容都需要前置),仅仅是时间上提前。
    也就是说,发生以下两种操作不一致:
    1. 输入 `/something/../something/` 提示配置错误
    2. 输入 `/something/.../something/` 没有提示配置错误,但访问相应 API 时发生错误
    第二种更加 insane,但却透过了前一层 sanity 过滤器。
    另外,指望正则检查越界感觉挺不稳妥的。且问下,用户是否有文件系统控制权?如果有,那么可以构造指向 / 的符号链接来跳过。如果没有,那么让用户任意输入一个路径就显得比较诡异。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2608 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 10:32 · PVG 18:32 · LAX 02:32 · JFK 05:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.