Regular Expression Syntax
Relevant source files
The following files were used as context for generating this wiki page:Regular expressions are a powerful tool used within the Self-Rule project, primarily for advanced network rule definitions and automated rule format conversions. While simple patterns like domain suffixes and keywords handle most cases, regex provides the flexibility to match complex and specific domain patterns required for fine-grained traffic control. The project's history shows a focus on not just using regex, but also on optimizing it for performance by reducing backtracking.
The primary applications of regular expressions are found in developer tooling, such as converting Surge-style rules to the ACL format and programmatically generating rule sets for sing-box.
Sources: Tool/New.md:82-84, Tool/Surge转acl工具/shortcuts.xml, update_sing_box.py
Core Applications
Rule Format Conversion
A key use of regular expressions is in the developer tooling for converting between different proxy rule formats. The Tool/Surge转acl工具/shortcuts.xml file defines a series of Notepad++ macros that use regex-based search-and-replace operations to automate these conversions.
Sources: Tool/Surge转acl工具/shortcuts.xml
Conversion Macros
The macros are designed to transform rule types like DOMAIN-SUFFIX and DOMAIN-KEYWORD from formats used by applications like Surge into a regex-based format compatible with ACL (Access Control List) files.
The following diagram illustrates the conversion process for a DOMAIN-SUFFIX rule into an ACL-compatible regular expression.
This diagram shows the two-step regex replacement process within the 网址转acl (URL to ACL) macro.
Sources: Tool/Surge转acl工具/shortcuts.xml:5-30
Key Regular Expression Patterns
The conversion macros rely on several key regular expression patterns to deconstruct the source rule and build the target regex rule.
| Macro Name | Regex Pattern | Description |
|---|---|---|
网址转acl (URL to ACL) | ^((DOMAIN-SUFFIX|DOMAIN)\,)|((.*)?http\w?\:\#(www\\\.)?) | Matches the prefix of a Surge rule (e.g., DOMAIN-SUFFIX,) or a raw URL. It is replaced with `(^ |
网址转acl (URL to ACL) | (\,\s?.{0,3}(Proxy|DIRECT|REJECT)(.*)?$)|(\/.*$) | Matches and removes the action part of the rule (e.g., ,PROXY) and any trailing characters, replacing it with $ to signify the end of the string. |
关键词转acl (Keyword to ACL) | DOMAIN-KEYWORD, | Matches the DOMAIN-KEYWORD, prefix. This is the first step in converting a keyword match to a full regex. |
关键词转acl (Keyword to ACL) | \,\s?.{0,3}(Proxy|DIRECT|REJECT)(.*)?$ | Matches and removes the action part of a keyword rule, replacing it with a regex suffix like \w*\\\.\.*$ to complete the pattern. |
去除注释 (Remove Comments) | (?<!:)//.* | A negative lookbehind is used to find and remove // style comments, but ignores them if they are part of a protocol string like http://. |
Sources: Tool/Surge转acl工具/shortcuts.xml:5-30, 32-55, 126-132
An update note in Tool/New.md provides a concrete example of converting a Surge DOMAIN-KEYWORD rule to a regex pattern:
DOMAIN-KEYWORD,admarvel,REJECT is changed to ^(.*\.)?.*admarvel.*\..*$
This demonstrates a manual or scripted conversion to create a robust regex that matches "admarvel" as a whole or partial segment of a domain name.
Sources: Tool/New.md:111-112
sing-box Rule Generation
The update_sing_box.py script demonstrates the programmatic use of regular expressions. It parses custom .list rule files and generates JSON rule sets for the sing-box application, which can then be compiled into the binary .srs format.
Sources: update_sing_box.py
Script Logic
The script iterates through rule files and identifies lines that define regex-based domain matching rules.
This flowchart shows how update_sing_box.py processes .list files to generate compiled sing-box rule sets, with a specific path for DOMAIN-REGEX rules.
Sources: update_sing_box.py:44-90
Data Structures and Parsing
The script uses a HeadlessRule dataclass to store parsed rules. The domain_regex field holds a list of all regular expression patterns.
# Source: update_sing_box.py:16-34
@dataclass
class HeadlessRule:
# ... other fields
domain_regex: list[str] = None
# ... other fields
def append(self, key: str, value: str):
if getattr(self, key) is None:
setattr(self, key, [])
getattr(self, key).append(value)
The script's main loop contains logic to identify and process DOMAIN-REGEX rules from the input files.
# Source: update_sing_box.py:68-71
# ...
elif line.split(",")[0] == "DOMAIN-REGEX":
headless_rule.append("domain_regex", line.split(",")[1])
# ...
This snippet shows the direct mapping from a DOMAIN-REGEX line in a .list file to the domain_regex attribute of the HeadlessRule object.
Sources: update_sing_box.py:16-34, 68-71
Related Pattern Matching Syntax
Besides full regular expressions, the project uses simpler pattern-matching mechanisms for defining rules. These are often preferred for their better performance and readability when complex matching is not required.
Wildcard Matching
The main Clash configuration file uses simple wildcards (*) in the cfw-bypass list to exempt certain domains and IP ranges from the proxy.
# Source: Clash/GeneralClashConfig.yml:220-222, 545-546
cfw-bypass:
# CN域名直连(中国|公司|网络)
- "*.cn"
- "*.xn--fiqs8s"
# ...
- 127.*
- 192.168.*
This syntax is less powerful than regex but is sufficient for matching entire sub-networks or top-level domains.
Sources: Clash/GeneralClashConfig.yml:218-550
Clash Rule Types
The provider files (.yaml) primarily use a set of predefined rule types that serve as alternatives to DOMAIN-REGEX.
| Rule Type | Description | Example | Source File |
|---|---|---|---|
DOMAIN-SUFFIX | Matches if the domain ends with the specified value. | google.com | Clash/Providers/ProxyGFWlist.yaml |
DOMAIN-KEYWORD | Matches if the specified keyword appears anywhere in the domain. | google | Clash/Providers/ProxyGFWlist.yaml |
IP-CIDR | Matches if the destination IP address is within the specified CIDR range. | 8.8.8.0/24 | Clash/Providers/ProxyGFWlist.yaml |
DOMAIN-REGEX | Matches the domain against a full regular expression. | (^|\\.)google\\.com$ | update_sing_box.py |
Sources: Clash/Providers/ProxyGFWlist.yaml, update_sing_box.py:70-71