Skip to content

script14好像有一个问题 #4

@av404

Description

@av404

大佬你好,我今天使用这个脚本的时候出现了一个问题,但是我看不懂,问了ai给出的解释能麻烦您看一下吗


你的覆写脚本在解析原配置的 rules 时,使用了简单的 split(',') 来切割规则字符串。当遇到 包含内嵌逗号 的 AND 规则时,这种切割方式会破坏规则的逻辑结构,导致生成错误的规则格式。


错误复现过程

原配置中有一条正确的 AND 规则:

- 'AND,((DST-PORT,443),(NETWORK,UDP)),REJECT'

脚本中的处理逻辑:

const p = r.split(',');   // 错误地用逗号切割整个规则

切割后得到的数组为:

0: 'AND'
1: '((DST-PORT'
2: '443)'
3: '(NETWORK'
4: 'UDP))'
5: 'REJECT'

接着脚本检测 p.length >= 3,并尝试修改 p[2](原为 '443)'):

if (!valid.has(p[2].trim())) p[2] = mapTarget(p[2]);

p[2] 为 '443)',不在 valid 集合中,于是被映射为 '节点选择'。

最终重新 join(',') 得到的字符串变为:

'AND,((DST-PORT,节点选择,(NETWORK,UDP)),REJECT'

括号数量不匹配(少了原本 443) 自带的右括号),因此 Clash 解析时报错:

format error is missing )

根本原因

覆写脚本对 rules 的处理过于简单,没有考虑 Clash 规则中可能存在的内嵌逗号(例如 DST-PORT,443 中的逗号)。这导致复杂规则(如 AND、OR、NOT 以及带有多个参数的规则)被错误切割和重组。


解决方案

修改覆写脚本,对复杂规则进行保护性处理,避免破坏其内部结构。推荐以下两种方式之一:

方案一:跳过复杂规则的修改(推荐)

在遍历规则时,如果规则以 AND,、OR,、NOT, 开头,则原样保留,不进行策略映射。

const custom = (config.rules || [])
    .filter(r => !r.startsWith("MATCH,"))
    .filter(r => !r.startsWith("RULE-SET,") || providerKeys.has(r.split(',')[1]))
    .map(r => {
      // 跳过复杂逻辑规则,避免破坏结构
      if (r.startsWith('AND,') || r.startsWith('OR,') || r.startsWith('NOT,')) {
        return r;
      }
      const p = r.split(',');
      if (p.length >= 3) {
        if (!valid.has(p[2].trim())) p[2] = mapTarget(p[2]);
        if (p[0].trim().includes("IP")) p[3] = "no-resolve";
      }
      return p.join(',');
    });

方案二:使用更精确的规则解析器

如果确实需要修改复杂规则内部的策略目标,应使用正则或专门的解析库(如 clash-rules-parser),确保正确处理引号及括号内的逗号。


总结

· 直接原因:split(',') 破坏了 AND 规则的内部结构,将 '443)' 替换为 '节点选择',导致括号丢失。
· 修复建议:在覆写脚本中跳过对 AND/OR/NOT 规则的修改,保持原样输出。

这样修改后,重新执行覆写即可正常生成配置文件。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions