【问题标题】:Comparing user-specific URL list with current URL?将用户特定的 URL 列表与当前 URL 进行比较?
【发布时间】:2015-03-08 18:25:29
【问题描述】:

我有一个白名单,用户可以在其中输入特定的 URL/URL 模式(仅针对 httphttps

我想转换并比较这些 URL/URL 模式,以便可以像这样使用 通配符选择器 (*)

用户输入: example.*/test

我想将其转换为: *//*.example.*/test

使其匹配: http://www.example.com/test, https://example.co.uk/test

另一个例子:

用户输入: http://www.*.com/*

我想将其转换为: http://www.*.com/*

使其匹配: http://www.blah.com/test, http://www.other.com/null.html

用户输入: www.example.com/*

我想将其转换为: *//www.example.com/*

使其匹配: http://www.example.com/testtwo, https://www.example.com/arfg

我想插入一个前导协议(如果它没有被用户包含的话)的原因是因为我正在使用它来与当前标签 URL 进行比较。

我得到了这个 URL 字符串数组并想将它们与当前 url 进行比较,但在匹配所有用例时遇到了问题:

 "isNotWhitelisted" : function(){
      var whitelist = MyObject.userLists.whitelist;
      var currentUrl = document.location.href;
      for(var i=0; i<whitelist.length; i++){
          var regexListItem = new RegExp(whitelist[i].toString().replace(".", "\\.").replace("*", ".+"));
          if(currentUrl.match(regexListItem)) {
              return false;
          }
      }
      return true;
  },
  1. 首先,正则表达式转换匹配结束情况(例如 example.com/*,但不匹配 example.*/about 之类的类型

  2. 这是 Chrome 扩展程序的一部分,难道没有更好/更简单的方法可以使用内置方法吗?

提前感谢您的帮助。

【问题讨论】:

  • 如果你不确定它是否正确,你不应该创建一个测试 url 的数组并为每个测试 url 设置一个标志,如果它应该通过吗?
  • 这可能会有所帮助:stackoverflow.com/questions/12433271/… Chrome 匹配模式的基于 JS 的实现。
  • 你的正则表达式转换错误;离开 . 而不是文字 \. 将无法正常工作。这只是一个问题。
  • 我不想讲太多细节; .+ 匹配(1+ 任意字符),但example.com 中剩余的句点也​​匹配任意字符; example_com/test 将匹配。
  • @Xan Ahh 我现在完全明白了,所以.replace(".", "\\.").replace("*", ".+") 会有所改进,但还有更多问题。为建议喝彩

标签: javascript arrays regex url google-chrome-extension


【解决方案1】:
whitelist.forEach(function(listItem){
     var rgx = new RegExp(listItem.replace(/\./g,'\\.').replace(/\*/g,'.*'));
     if(rgx.test(url)) {
       // current URL matches URL/URL pattern in whitelist array! 
     }  
  })

如果不替换,模式 'www.*.com' 也匹配 'wwwocom'。

如果你想使用其他特殊字符,你可以使用这个:

var rgx = new RegExp(listItem.replace(/(\.|\[|\]|\{|\}|\(|\)|\+|\?|\\|\$|\^)/g,'\\$1').replace(/\*/g,'.*'));

【讨论】:

  • .replace(/\*/g,'.*')) 应该是 .replace(/\*/g,'.+')),因为他不希望 * 解析为 null。
  • 我不知道他想要什么,但* 在通配符中是.* 在正则表达式中。
  • 我觉得他说的很形象:I want * to be a wildcard selector, so www.example.com/* would match anything not-null 。他将* 通配符定义为任何非空值
  • 他没说的是贪心匹配,或者参数是否包含匹配约束http://www.example.com?url=anothersite.comhttp://nonmatchingsite.com?url=http://www.example.com
  • 他给出了没有协议的模式,所以它们不能贪婪匹配。
【解决方案2】:

如果你想要一个贪心匹配,我认为你需要请求用户以这种格式输入模式:*://*/*

你可以这样检查:

var special_char_rgx = /(\.|\[|\]|\{|\}|\(|\)|\+|\?|\\|\/|\$|\^|\|)/g; // I think that all...
var asterisk_rgx = /\*/g;
var pattern_rgx = /^([^:\/]+):\/\/([^\/]+)\/(.*)$/g;

function addPatern(pattern, whitelist) {
    var str_pattern = pattern.replace(asterisk_rgx,'\\*');
    var isMatch = pattern_rgx.test(str_pattern);
    if (isMatch) {
        pattern = pattern.replace(special_char_rgx,'\\$1').replace(asterisk_rgx, '.+');
        whitelist.push(new RegExp('^'+pattern + '$'));
    }

    pattern_rgx.lastIndex = 0; // Otherwise RegExp.test save this value and destroy the tests!

    return isMatch;
}

如果你想以不同的方式处理协议/域/路径,你可以这样做:

    if (isMatch) {
        var protocol = RegExp.$1;
        var domain= RegExp.$2;
        var path_query = RegExp.$3;            
        // Your logic...
    }

【讨论】:

  • 我用几个例子更新了这个问题。感谢您的回答 +1
【解决方案3】:

嗯,m.b.从白名单项目创建 RegExp?如果它按您的预期工作:

new RegExp('example.com/*').test('http://example.com/aaaa')

只需从白名单中的每个项目创建正则表达式

whitelist.forEach(function(item) {
  new RegExp(item).match(URL);
});

【讨论】:

  • new RegExp('www.*.com').test('wwwocom.org') // 对!您需要替换特殊字符
  • 这是大错特错。正则表达式的语法使得其中一些模式可以编译为有效,但在所有情况下其含义都是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 2014-02-18
相关资源
最近更新 更多