【问题标题】:Regular expression to match the specific request parameters in a url正则表达式匹配 url 中的特定请求参数
【发布时间】:2018-06-09 01:44:22
【问题描述】:

我有一个网址 (https://example.com?&iframeLoad=true&firstName=&lastName=&email=&phone1=&address=&zipcode=07307&isAvailableReferral=true&isAvailableDirect=false)

我正在尝试替换名字、姓氏、电子邮件、电话、地址字段,而不是其他字段。

这是我目前使用正则表达式所做的 (&?(firstName|lastName|email|phone1|address)=?[^&]*)

这基本上选择了“&”,然后是名字|姓氏|电子邮件|电话1|地址以及“=”之后的每个字符。请注意,如果“=”后跟“&”符号,则正则表达式不匹配。

我能够正确选择每个字段,但是当 URL 在“=”之后有一个“&”时,我的解决方案无法正常工作,因为它只选择“&”字符之前的值。

作为一个有效的电子邮件可以有一个“&”。我需要一个解决方案,即使“=”之后有“&”符号,正则表达式也会选择。

示例:&email=abc&xyz@.com - 在这种情况下,正则表达式只选择“&email=abc&”而不是整个电子邮件。

【问题讨论】:

  • 考虑使用 url 解析器
  • 通常,URL 中的 & 字符将被 URL 编码:%26
  • 您使用的正则表达式是什么编程语言/程序?由于正则表达式是特定于平台的,并且某些正则表达式引擎支持的功能比其他引擎更多,因此这与问题非常相关。
  • 我在使用 javascript 匹配后替换字符串。 @格雷厄姆
  • 感谢您的帮助! @DavidFaber 和丹尼尔

标签: javascript regex regex-negation regex-group


【解决方案1】:

根据 url 编码的规范,此任务可能无法明确完成。为了实现这一点,数据集中的 url 必须标准化,以便每个参数后面都有一个等号,并且参数值中不能有其他杂散的等号。如果这两个条件都为真,那么以下将起作用:

正则表达式

&(firstName|lastName|email|phone1|address)=([^&]*(?:&[^&=]+(?=&|$))*)

另请注意,此正则表达式不涵盖其中一个所需参数是第一个参数的情况。因为 Javascript 正则表达式是有限的,而且无论如何这是一个特殊情况(以 ? 而不是 & 开头),这将需要以不同的方式处理,具体取决于您要对参数执行的操作。匹配以下并替换为?是一种删除参数的方法:

\?(firstName|lastName|email|phone1|address)=([^&]*(?:&[^&=]+(?=&|$))*)(?:&|$)

如果您不打算完全删除该参数,可以删除表达式末尾的 (?:&|$) 为简单起见。

根据您打算用什么替换参数,您可能会发现调整表达式很有用,但这些通常应该在上述规则内给出所需的输出。

工作原理

这里的诀窍是有一个单独的非捕获组(?:&[^&=]+(?=&|$))*,它处理带有原始 & 符号但没有等号的参数字符串的其他部分。字符类[^&=]+ 确保子表达式没有和号或等号,前瞻(?=&|$) 确保字符串后跟另一个参数或字符串结尾,而不是等号。整个组有一个量词*,因为它可以在初始参数之后出现零次、一次或多次。

另外注意,为方便起见,参数名和值的值存放在capturing groups1和2中,方便访问和解析。如果您不打算使用这些值,可以通过在 ( 后添加 ?: 将它们替换为非捕获组。

免责声明

如果任何参数缺少等号,则无法明确区分新 url 参数与前一个 url 参数的值,因为在示例 https://example.com?&iframeLoad=true&email=abc&xyz@.com 中,这可能是指一个名为 email 的参数值abc&xyz@.com,或两个名为emailxyz@.com 的参数(除非参数字符串列表和值字符串列表都是标准化的,但这条路是疯狂的)。以类似的方式,随机等号欺骗解析器。正如@David Faber 所提到的,通常 URL 中的 & 字符将被 URL 编码为 %26,以完全防止这种歧义。

【讨论】:

  • 非常感谢!这正是我想要实现的。感谢您的详细解释:) @Graham
【解决方案2】:

您可能需要考虑这样的事情:

[&?]((?:firstName|lastName|phone1|address|zipcode)=|email=(?:.*@.*\.)?)[^&]*

email 参数在此处作为特殊情况处理 - 我们检查本地部分后跟子域,同时允许不带 & 符号的 TLD(我相信这是安全的 - 我不认为TLD 可以包含这样的奇数字符)。所有其他参数都正常处理。匹配项将作为名称=值对返回。 See Regex 101 here.

【讨论】:

  • 我不会推荐这种方法。首先,email address validation can be complicated。即使您想采用这种方法,您也应该避免使用.* 构造,以提高效率和potential failure cases。此解决方案也不足以满足 OP 的 替换 url 中文本的要求:对于替换,知道第一个字符至关重要,但无法从该表达式中知道它。
  • 我绝对不建议在这里进行任何形式的电子邮件验证。我同意.* 最好避免使用。
  • 一般来说,我认为任何类型的电子邮件验证在这里都是一种不好的方法,因为它假设输入是合法的电子邮件,我们不一定能假设。但是,如果您正在使用(基本)电子邮件验证方法,并且您允许替换,那么您真正想要的正则表达式是([&?])((?:firstName|lastName|phone1|address|zipcode)=|email=(?:[^@]*@)?[^&]*)。此外,我在解决方案中使用了两个单独的正则表达式,因为第一个参数的删除处理会有所不同。
  • @Graham,谢谢,这比我最初的正则表达式更好
猜你喜欢
  • 1970-01-01
  • 2017-12-01
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
  • 2020-12-19
相关资源
最近更新 更多