【问题标题】:JavaScript Regex to match a URL in a field of textJavaScript 正则表达式匹配文本字段中的 URL
【发布时间】:2011-11-18 20:23:18
【问题描述】:

如何设置我的正则表达式来测试一个 URL 是否包含在 javascript 的文本块中。我无法完全弄清楚用于完成此操作的模式

 var urlpattern = new RegExp( "(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?"

 var txtfield = $('#msg').val() /*this is a textarea*/

 if ( urlpattern.test(txtfield) ){
        //do something about it
 }

编辑:

所以我现在拥有的模式可以在正则表达式测试器中用于我需要它做的事情,但 chrome 会引发错误

  "Invalid regular expression: /(http|ftp|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&:/~+#]*[w-@?^=%&/~+#])?/: Range out of order in character class"

以下代码:

var urlexp = new RegExp( '(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?' );

【问题讨论】:

  • 为什么要排除 FTPS?
  • 我真的只需要 http/https 所以在我的情况下我也可以省略 ftp
  • 这本质上是How to replace plain URLs with links? 的复制品,这就解释了为什么正则表达式不适合这类任务。

标签: javascript jquery regex


【解决方案1】:

虽然转义破折号字符(在字符类中作为字符范围说明符具有特殊含义)应该起作用,但另一种消除其特殊含义的方法是将它们放在开头或类定义的结尾。

另外,字符类中的\+\@确实被JavaScript引擎分别解释为+@;但是,转义不是必需的,可能会使试图直观地解释正则表达式的人感到困惑。

我会为您推荐以下正则表达式:

(http|ftp|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?

这可以在 JavaScript 中通过将其传递给 RegExp 构造函数来指定(就像您在示例中所做的那样):

var urlPattern = new RegExp("(http|ftp|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?")

或通过直接指定正则表达式文字,使用// 引用方法:

var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/

如果您接受正则表达式作为字符串(例如来自用户输入或 AJAX 调用),则 RegExp 构造函数是必需的,并且可能更具可读性(如本例所示)。我相当肯定// 引用方法更有效,并且在某些时候更具可读性。两者都有效。

我在 JSFiddle> 和 RegexLib.com> 上使用 Chrome 测试了您的原始版本和此修改,使用客户端正则表达式引擎(浏览器)并特别选择了 JavaScript。虽然第一个因您所说的错误而失败,但我建议的修改成功。如果我从源中的http 中删除h,它将无法匹配!

编辑

正如 cmets 中 @noa 所指出的,上面的表达式将不匹配本地网络(非互联网)服务器或任何其他使用单个词访问的服务器(例如 http://localhost/... 或 https://sharepoint-test-server/... )。如果需要匹配这种类型的 url(可能是也可能不是),以下可能更合适:

(http|ftp|https)://[\w-]+(\.[\w-]+)*([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?

#------changed----here-------------^

结束编辑>

最后,Regular-Expressions.info 是一个很好的资源,它教会了我 90% 的正则表达式知识——如果你想学习正则表达式,我强烈推荐它(包括它能做什么和不能做什么)!

【讨论】:

  • 正则表达式信息已损坏。在 href 中放置“点”而不是破折号。
  • 还有一件事:正确的语法应该是 ... = new RegExp(...) 而不是 ... = new Regexp(...)。无论如何,感谢您的出色回答!
  • 这会破坏主机中没有点的 URL。例如,http://localhost/foo/bar.txt。要修复它,请将 (\.[\w-]+)+ 更改为 (\.[\w-]+)*
  • 这个问题很笼统,这个答案得到了很多人的认可。有人(不是 OP)使用了这段代码,它在我正在调试的一些代码中造成了一个真正的错误……所以中断不是完全相对的。让答案尽可能规范是值得的。
  • 我强烈推荐这个作为补充资源:mathiasbynens.be/demo/url-regex
【解决方案2】:

完整的多 URL 模式。

更新日期:2020 年 11 月、2021 年 4 月和 6 月(感谢评论者)

匹配字符串中的所有 URI 或 URL! 还提取协议、域、路径、查询和哈希。 ([a-z0-9-]+\:\/+)([^\/\s]+)([a-z0-9\-@\^=%&;\/~\+]*)[\?]?([^ \#\r\n]*)#?([^ \#\r\n]*)

https://regex101.com/r/jO8bC4/56

带有输出的示例 JS 代码 - 每个 URL 都被转换为其“部分”(协议、主机、路径、查询和哈希)的 5 部分数组

var re = /([a-z0-9-]+\:\/+)([^\/\s]+)([a-z0-9\-@\^=%&;\/~\+]*)[\?]?([^ \#\r\n]*)#?([^ \#\r\n]*)/mig;
var str = 'Bob: Hey there, have you checked https://www.facebook.com ?\n(ignore) https://github.com/justsml?tab=activity#top (ignore this too)';
var m;

while ((m = re.exec(str)) !== null) {
    if (m.index === re.lastIndex) {
        re.lastIndex++;
    }
    console.log(m);
}

将为您提供以下内容:

["https://www.facebook.com",
  "https://",
  "www.facebook.com",
  "",
  "",
  ""
]

["https://github.com/justsml?tab=activity#top",
  "https://",
  "github.com",
  "/justsml",
  "tab=activity",
  "top"
]

【讨论】:

  • 这是一个超级聪明的方法+1
  • 您的正则表达式没有区分文本块和 URL。检查here
  • 更新了我的答案——在我的示例代码前面包含@noob 的建议字符串(因此它非常可靠地提取所有类似 url 的字符串——即使有一个冒号前缀的字符串。使用显式匹配斜线来描述协议)。也适用于 smb:///winbox/dfs/ipp://printer regex101.com/r/jO8bC4/5
  • BAM "a a:// . " 使用此正则表达式返回 true :/
  • 嘿@vsync - 谢谢,现在域需要1个或更多字符!
【解决方案3】:

当您使用new RegExp 时,您必须转义反斜杠。

您也可以将破折​​号- 放在字符类的末尾以避免转义。

& 在字符类中表示 & or a or m or p or ; ,您只需将 &;a, m and p 已经与 \w 匹配。

所以,你的正则表达式变成:

var urlexp = new RegExp( '(http|ftp|https)://[\\w-]+(\\.[\\w-]+)+([\\w-.,@?^=%&:/~+#-]*[\\w@?^=%&;/~+#-])?' );

【讨论】:

  • 如何扩展它以匹配多个url?
【解决方案4】:

试试(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?

【讨论】:

  • 当使用这个时,我得到一个错误 Range out of order in character class"
【解决方案5】:

我已经清理了你的正则表达式:

var urlexp = new RegExp('(http|ftp|https)://[a-z0-9\-_]+(\.[a-z0-9\-_]+)+([a-z0-9\-\.,@\?^=%&;:/~\+#]*[a-z0-9\-@\?^=%&;/~\+#])?', 'i');

经过测试并且工作正常;)

【讨论】:

  • 如何扩展它以匹配多个 url? ——
  • 添加“全局”修饰符 (g): new RegExp(.., 'gi')
【解决方案6】:

对许多 URL 格式尝试这个通用正则表达式

/(([A-Za-z]{3,9})://)?([-;:&=\+\$,\w]+@{1})?(([-A-Za-z0-9]+\.)+[A-Za-z]{2,3})(:\d+)?((/[-\+~%/\.\w]+)?/?([&?][-\+=&;%@\.\w]+)?(#[\w]+)?)?/g

【讨论】:

    【解决方案7】:

    问题在于字符类(括号)中的“-”被解析为一个范围:[a-z] 表示“a 和 z 之间的任何字符”。正如 Vini-T 建议的那样,您需要使用反斜杠转义字符类中的“-”字符。

    【讨论】:

      【解决方案8】:

      试试这个对我有用

      /^((ftp|http[s]?):\/\/)?(www\.)([a-z0-9]+)\.[a-z]{2,5}(\.[a-z]{2})?$/
      

      就是这么简单易懂

      【讨论】:

        猜你喜欢
        • 2011-02-19
        • 2021-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多