用户脚本中的@include 和@match 有什么区别?
What is the difference between @include and @match in userscripts?
GreaseSpot page on metadata blocks says that the two are very similar but @match
"sets more strict rules on what the *
character means." GreaseSpot then proceeds to teach using @include
, but Chrome examples like this一般好像用@match
表示支持@include
只是为了兼容; @match
优先。
Apparently、@include google.*
可以在 google.evil.com 上 运行 而 @match google.*
不能。
一个例子不足以真正了解通配符在这两者之间的行为有何不同,请在此处的答案中寻求更好的解释。
新的 GreaseMonkey 脚本 (Firefox) 默认使用 @include
而新的 TamperMonkey 脚本(例如 Chrome)默认使用 @match
。
这两者到底有什么区别?
例如,每个人如何处理通配符?
跨浏览器兼容性是否存在差异?
人们有什么理由选择使用其中之一?
您不能对 @match
使用正则表达式,而 can 对 @include
。
但是,@include
将向您的用户发出有关该脚本适用于所有站点的更可怕的安全警告。
尽管 @include
表达式允许您对脚本适用的站点 更具限制性(例如指定 URL 使用正则表达式片段 [0-9]+
或使用 ^https?://
将这两个方案应用于脚本,而不是用于每个方案的更通用的非正则表达式 globbing 运算符 *
@match
中的案例,这导致脚本的应用范围更广)。
TL;DR:刚度
最重要的区别是 @match
比 @include
更严格、更严格,旨在成为更安全的替代方案。因此,@include
也可能会向最终用户生成更可怕的警告;整体使用起来也有点复杂,这取决于你如何看待它。
两者的实际用法实际上可以有很大的不同;下面是每个用法的完整细分。
@include
(和@exclude
)
@include
可能是大多数人更熟悉的指令(连同它的对立双胞胎,@exclude
,它们具有完全相同的语法特征)。这是两者中更强大的指令,主要是因为它可以处理 RegEx 模式(这也意味着它会生成更可怕的警告)。它的用法也是两者中最直接的。
模式
您可以通过两种方式指定模式/“模式”:
全局模式
星号 *
可用作 wildcard glob,即表示 任意 个字符,包括零。
@include http://www.example.com/foo/*
:
- 匹配
http://www.example.com/foo/
和 http://www.example.com/foo/bar
- 不匹配
http://www.example.com/baz
还有一个特殊模式可用于专门匹配任何顶级域后缀:.tld
.
像 @include https://www.example.tld/*
这样的模式将匹配具有 任何顶级域 后缀的给定域,例如 .com
、.org
、或 .co.uk
.
正则表达式模式
@include
以 /
字符开头的指令将被解释为正则表达式,具有所有可用的标准 JavaScript RegEx 功能:
// ==UserScript==
// @include /^https?://www\.example\.com/.*$/
// @include /^http://www\.example\.(?:org|net)//
// ==/UserScript==
一些注意事项:
- 由于 JavaScript 的 RegEx 解释,正斜杠
/
不需要在表达式中转义。
- Other special characters还需要转义
@include
模式总是被视为 不区分大小写。
- 不以 EOL 标记结尾的表达式
$
将隐式允许匹配项中的尾随字符。
- 换句话说,表达式被视为以
.*
结尾。
@include /^https?://www\.google\.com/search/
将匹配 https://www.google.com/search?q=Whosebug
.
警告
请记住,@include
的强大特性意味着浏览器无法像使用 @match
的脚本那样保证给定脚本的目标;这意味着使用 @include
的脚本可能会为用户触发更可怕和严重的警告。
不使用 @include
的一个常见原因涉及 URL 片段(散列 #
字符后的 URL 部分),以及恶意行为者如何能够滥用它们在不需要的页面上执行脚本(例如 @include http://*.example.com/
可以匹配 www.evil.com#www.example.com/
),因为 @match
在设计上会忽略片段。
虽然这种攻击在理论上仍然是可能的,但值得记住的是,一些用户脚本管理器(包括 Tampermonkey)为了匹配目的故意完全忽略片段,即使在 @include
指令中也是如此。
@match
@match
指令是 Google 为 Chrome 创建的,被设计为 @include
指令的更安全、更沙盒化的版本,更多 更坚固的内置。
不是允许 glob 或 RegEx,@match
将模式解释为 3 个部分:方案、主机、和 路径 。 Google's documentation 这样描述基本语法:
<url-pattern> := <scheme>://<host><path>
<scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'urn'
<host> := '*' | '*.' <any char except '/' and '*'>+
<path> := '/' <any chars>
模式的每一部分都有自己的注意事项,并且对通配符*
的解释也不同。
方案
URL 模式的方案部分必须与支持的方案之一(这似乎取决于浏览器)或通配符 *
.
完全匹配
- 在 Chrome 中,即:
http
、https
、file
、ftp
或 urn
。
- In Firefox,好像是
http
、https
、file
、ftp
、ws
、wss
, data
, 或 (chrome-
)extension
.
在这部分模式中,通配符 *
只匹配 http
或 https
(MDN mentions 它可能在某些浏览器中也匹配 WebSocket 方案 ws
和 wss
。
主持人
URL 模式的主机部分可以采用三种样式:
- 完全明确:
www.whosebug.com
- 子域通配符:
*.whosebug.com
- 完全通配符:
*
顶级域名后缀不能为通配符(如www.Whosebug.*
); this is disallowed for security reasons。为了匹配多个 TLD 后缀,脚本需要为每个后缀包含一个特定的 @match
指令。
路径
URL 模式的路径部分是 3 种模式中最宽松的,因为唯一的规则是它必须以正斜杠 /
开头。其余可以是字符和通配符的任意组合。
在本节中,通配符 *
充当标准的 glob 运算符,仅匹配 0 个或多个字符。
与模式的路径部分匹配的值正式是 URL 路径 加上 URL 查询字符串(例如。在google.com/search?q=test
中,查询字符串是q=test
),包括?
之间。对于旨在匹配给定域结尾的模式来说,这是一个潜在的陷阱,因为它们可能会被添加的查询字符串挫败。
另请注意,该路径 不 包括 URL 片段(末尾的 URL 部分跟随散列 #
,例如 www.example.com#main
); @match
指令故意忽略 URL 片段以防止滥用无意的匹配。
注意事项
这很明显,但值得重复的是,脚本应该小心 @include
完全 和 独占 URL 表示该脚本将 运行 启用。失控脚本的范围从无法检测到的小麻烦到大问题不等;始终仔细检查脚本 运行 只在它们应该在的位置,并在必要或方便时使用 @exclude
添加防护栏。
GreaseSpot page on metadata blocks says that the two are very similar but @match
"sets more strict rules on what the *
character means." GreaseSpot then proceeds to teach using @include
, but Chrome examples like this一般好像用@match
表示支持@include
只是为了兼容; @match
优先。
Apparently、@include google.*
可以在 google.evil.com 上 运行 而 @match google.*
不能。
一个例子不足以真正了解通配符在这两者之间的行为有何不同,请在此处的答案中寻求更好的解释。
新的 GreaseMonkey 脚本 (Firefox) 默认使用 @include
而新的 TamperMonkey 脚本(例如 Chrome)默认使用 @match
。
这两者到底有什么区别?
例如,每个人如何处理通配符?
跨浏览器兼容性是否存在差异?
人们有什么理由选择使用其中之一?
您不能对 @match
使用正则表达式,而 can 对 @include
。
但是,@include
将向您的用户发出有关该脚本适用于所有站点的更可怕的安全警告。
尽管 @include
表达式允许您对脚本适用的站点 更具限制性(例如指定 URL 使用正则表达式片段 [0-9]+
或使用 ^https?://
将这两个方案应用于脚本,而不是用于每个方案的更通用的非正则表达式 globbing 运算符 *
@match
中的案例,这导致脚本的应用范围更广)。
TL;DR:刚度
最重要的区别是 @match
比 @include
更严格、更严格,旨在成为更安全的替代方案。因此,@include
也可能会向最终用户生成更可怕的警告;整体使用起来也有点复杂,这取决于你如何看待它。
两者的实际用法实际上可以有很大的不同;下面是每个用法的完整细分。
@include
(和@exclude
)
@include
可能是大多数人更熟悉的指令(连同它的对立双胞胎,@exclude
,它们具有完全相同的语法特征)。这是两者中更强大的指令,主要是因为它可以处理 RegEx 模式(这也意味着它会生成更可怕的警告)。它的用法也是两者中最直接的。
模式
您可以通过两种方式指定模式/“模式”:
全局模式
星号 *
可用作 wildcard glob,即表示 任意 个字符,包括零。
@include http://www.example.com/foo/*
:- 匹配
http://www.example.com/foo/
和http://www.example.com/foo/bar
- 不匹配
http://www.example.com/baz
- 匹配
还有一个特殊模式可用于专门匹配任何顶级域后缀:.tld
.
像 @include https://www.example.tld/*
这样的模式将匹配具有 任何顶级域 后缀的给定域,例如 .com
、.org
、或 .co.uk
.
正则表达式模式
@include
以 /
字符开头的指令将被解释为正则表达式,具有所有可用的标准 JavaScript RegEx 功能:
// ==UserScript==
// @include /^https?://www\.example\.com/.*$/
// @include /^http://www\.example\.(?:org|net)//
// ==/UserScript==
一些注意事项:
- 由于 JavaScript 的 RegEx 解释,正斜杠
/
不需要在表达式中转义。 - Other special characters还需要转义
@include
模式总是被视为 不区分大小写。- 不以 EOL 标记结尾的表达式
$
将隐式允许匹配项中的尾随字符。- 换句话说,表达式被视为以
.*
结尾。 @include /^https?://www\.google\.com/search/
将匹配https://www.google.com/search?q=Whosebug
.
- 换句话说,表达式被视为以
警告
请记住,@include
的强大特性意味着浏览器无法像使用 @match
的脚本那样保证给定脚本的目标;这意味着使用 @include
的脚本可能会为用户触发更可怕和严重的警告。
不使用 @include
的一个常见原因涉及 URL 片段(散列 #
字符后的 URL 部分),以及恶意行为者如何能够滥用它们在不需要的页面上执行脚本(例如 @include http://*.example.com/
可以匹配 www.evil.com#www.example.com/
),因为 @match
在设计上会忽略片段。
虽然这种攻击在理论上仍然是可能的,但值得记住的是,一些用户脚本管理器(包括 Tampermonkey)为了匹配目的故意完全忽略片段,即使在 @include
指令中也是如此。
@match
@match
指令是 Google 为 Chrome 创建的,被设计为 @include
指令的更安全、更沙盒化的版本,更多 更坚固的内置。
不是允许 glob 或 RegEx,@match
将模式解释为 3 个部分:方案、主机、和 路径 。 Google's documentation 这样描述基本语法:
<url-pattern> := <scheme>://<host><path>
<scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'urn'
<host> := '*' | '*.' <any char except '/' and '*'>+
<path> := '/' <any chars>
模式的每一部分都有自己的注意事项,并且对通配符*
的解释也不同。
方案
URL 模式的方案部分必须与支持的方案之一(这似乎取决于浏览器)或通配符 *
.
- 在 Chrome 中,即:
http
、https
、file
、ftp
或urn
。 - In Firefox,好像是
http
、https
、file
、ftp
、ws
、wss
,data
, 或 (chrome-
)extension
.
在这部分模式中,通配符 *
只匹配 http
或 https
(MDN mentions 它可能在某些浏览器中也匹配 WebSocket 方案 ws
和 wss
。
主持人
URL 模式的主机部分可以采用三种样式:
- 完全明确:
www.whosebug.com
- 子域通配符:
*.whosebug.com
- 完全通配符:
*
顶级域名后缀不能为通配符(如www.Whosebug.*
); this is disallowed for security reasons。为了匹配多个 TLD 后缀,脚本需要为每个后缀包含一个特定的 @match
指令。
路径
URL 模式的路径部分是 3 种模式中最宽松的,因为唯一的规则是它必须以正斜杠 /
开头。其余可以是字符和通配符的任意组合。
在本节中,通配符 *
充当标准的 glob 运算符,仅匹配 0 个或多个字符。
与模式的路径部分匹配的值正式是 URL 路径 加上 URL 查询字符串(例如。在google.com/search?q=test
中,查询字符串是q=test
),包括?
之间。对于旨在匹配给定域结尾的模式来说,这是一个潜在的陷阱,因为它们可能会被添加的查询字符串挫败。
另请注意,该路径 不 包括 URL 片段(末尾的 URL 部分跟随散列 #
,例如 www.example.com#main
); @match
指令故意忽略 URL 片段以防止滥用无意的匹配。
注意事项
这很明显,但值得重复的是,脚本应该小心 @include
完全 和 独占 URL 表示该脚本将 运行 启用。失控脚本的范围从无法检测到的小麻烦到大问题不等;始终仔细检查脚本 运行 只在它们应该在的位置,并在必要或方便时使用 @exclude
添加防护栏。