在正则表达式中强制匹配 filename*= over filename=
Force match on filename*= over filename= in regular expression
我有一个 Content-Disposition header 这样的:
Content-Disposition: attachment; filename="övrigt.xlsx"; filename*=utf-8''%C3%B6vrigt.xlsx
根据规范,有一个 filename="filename.extension"
and/or filename*=charencoding''filename.extension
。当文件名*存在时,它应该用于文件名。
所以我想在 filename*
属性中捕获 filename
属性中存在的文件名和字符编码。我最终得到了这个正则表达式:
filename\*?=(?:([^'"]*)''|("))([^;]+)(?:[;`\n]|$)
它工作正常,我唯一的问题是它与第一个匹配,文件名*或文件名:
attachment; filename*=utf-8''%C3%B6vrigt.xlsx; filename="övrigt.xlsx"
匹配项:
Match 1
Full match 12-45 filename*=utf-8''%C3%B6vrigt.xlsx;
Group 1. n/a utf-8
Group 3. n/a %C3%B6vrigt.xlsx
attachment; filename="övrigt.xlsx"; filename*=utf-8''%C3%B6vrigt.xlsx
匹配项:
Match 1
Full match 12-35 filename="övrigt.xlsx";
Group 2. n/a "
Group 3. n/a övrigt.xlsx
第 1 组始终匹配存在的字符编码。
第 3 组始终匹配文件名。
所以我现在可以在 group1 不为空时使用文件名和解码...
所以进入问题:
据我了解 *?应该贪婪地尝试将文件名与 * (see reference here):
匹配
The question mark is the first metacharacter introduced by this tutorial that is greedy. The question mark gives the regex engine two choices: try to match the part the question mark applies to, or do not try to match it. The engine always tries to match that part. Only if this causes the entire regular expression to fail, will the engine try ignoring the part the question mark applies to.
为什么它没有按预期工作,我做错了什么。如果存在,我怎样才能实现 filename*=
超过 filename=
的匹配。
假设只有一个匹配预期,并且预计该匹配是最后一次匹配出现,您可以使用
(?:.*filename\*|filename)=(?:([^'"]*)''|("))([^;]+)(?:[;`\n]|$)
参见regex demo。
我修改的部分是=
之前的部分,注意=
之后的部分可能也需要调整,但这不是重点。
(?:.*filename\*|filename)
non-capturing group 包含两个选项:
.*filename\*
- 除换行字符外的任何零个或多个字符,尽可能多,然后是 filename*
substring
|
- 或
filename
- 只是一个 filename
子串。
为什么有效:
- 正则表达式引擎开始从左到右解析字符串
- 触发非捕获组模式并尝试第一个替代方案
.*filename\*
如果在当前位置 右边的任意位置有 filename*
将匹配
- 如果没有
filename*
第二种选择,filename
将在字符串中的每个位置进行搜索,一旦找到,就会进行匹配。否则,根本就没有比赛。
我有一个 Content-Disposition header 这样的:
Content-Disposition: attachment; filename="övrigt.xlsx"; filename*=utf-8''%C3%B6vrigt.xlsx
根据规范,有一个 filename="filename.extension"
and/or filename*=charencoding''filename.extension
。当文件名*存在时,它应该用于文件名。
所以我想在 filename*
属性中捕获 filename
属性中存在的文件名和字符编码。我最终得到了这个正则表达式:
filename\*?=(?:([^'"]*)''|("))([^;]+)(?:[;`\n]|$)
它工作正常,我唯一的问题是它与第一个匹配,文件名*或文件名:
attachment; filename*=utf-8''%C3%B6vrigt.xlsx; filename="övrigt.xlsx"
匹配项:
Match 1
Full match 12-45 filename*=utf-8''%C3%B6vrigt.xlsx;
Group 1. n/a utf-8
Group 3. n/a %C3%B6vrigt.xlsx
attachment; filename="övrigt.xlsx"; filename*=utf-8''%C3%B6vrigt.xlsx
匹配项:
Match 1
Full match 12-35 filename="övrigt.xlsx";
Group 2. n/a "
Group 3. n/a övrigt.xlsx
第 1 组始终匹配存在的字符编码。
第 3 组始终匹配文件名。
所以我现在可以在 group1 不为空时使用文件名和解码...
所以进入问题:
据我了解 *?应该贪婪地尝试将文件名与 * (see reference here):
匹配The question mark is the first metacharacter introduced by this tutorial that is greedy. The question mark gives the regex engine two choices: try to match the part the question mark applies to, or do not try to match it. The engine always tries to match that part. Only if this causes the entire regular expression to fail, will the engine try ignoring the part the question mark applies to.
为什么它没有按预期工作,我做错了什么。如果存在,我怎样才能实现 filename*=
超过 filename=
的匹配。
假设只有一个匹配预期,并且预计该匹配是最后一次匹配出现,您可以使用
(?:.*filename\*|filename)=(?:([^'"]*)''|("))([^;]+)(?:[;`\n]|$)
参见regex demo。
我修改的部分是=
之前的部分,注意=
之后的部分可能也需要调整,但这不是重点。
(?:.*filename\*|filename)
non-capturing group 包含两个选项:
.*filename\*
- 除换行字符外的任何零个或多个字符,尽可能多,然后是filename*
substring|
- 或filename
- 只是一个filename
子串。
为什么有效:
- 正则表达式引擎开始从左到右解析字符串
- 触发非捕获组模式并尝试第一个替代方案
.*filename\*
如果在当前位置 右边的任意位置有 - 如果没有
filename*
第二种选择,filename
将在字符串中的每个位置进行搜索,一旦找到,就会进行匹配。否则,根本就没有比赛。
filename*
将匹配