RegEx匹配逗号分隔的主机名

时间:2015-01-20 23:42:13

标签: javascript regex

问题

我正在尝试使用JavaScript验证<textarea>的内容,因此我创建了一个validate()函数,该函数返回truefalse textarea是否有效。

textarea只能包含以逗号分隔的主机名。通过主机名,我的意思是subdomain.domain.com,所以它基本上是一些点分隔的字符串。由于用户不喜欢写得很好,我还想允许在各种主机名和逗号之间留下任何数量的空格,但不在主机名中。

以下是应该或不应该匹配的一些示例:

  • 应匹配:

    • domain.com,domain2.co.vu,sub.domain.org
    • ​ domai2n.com , dom-ain.org.co.vu.nl ,domain.it ​
    • dom-ain.it, domain.com, domain.eu.org.something
    • a.b.c, a.b, a.a.a , a.r
    • 0191481.com
  • 不匹配:

    • domain.com., sub.domain.it不完整的主机名
    • domain.me, domain2不完整的主机名
    • sub.sub.sub.domain.tv, do main.it主机名包含空格
    • site不完整的主机名
    • hèy.com主机名不能包含重音
    • hey.01com主机名不能以包含数字的数字或字符串结尾
    • hello.org..wow不完整的主机名

到目前为止我尝试了什么

我使用以下代码构建了我的函数:

function validate(text) {
    return (
        (/^([a-z0-9\-\.]+ *, *)*[a-z0-9\-\.]+[^, ]$/i.test(text) 
        && !/\.[^a-z]|\.$/i.test(text)
        && ~text.indexOf('.'))
    );
}

不幸的是,我的功能不起作用。它无法识别不完整的主机名并返回true

有没有办法实现这个目标?也许没有使用RegExps,即使我更喜欢使用一个RegExp。

6 个答案:

答案 0 :(得分:2)

说不使用正则表达式的答案非常好,但我喜欢正则表达式:

^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*)*$

是的..它不那么漂亮。但它有效 - 在http://regex101.com

上对您的示例案例进行了测试

编辑:好的,让我们分解吧。并且只允许sub-domain-01.coma--b.com而不是-.com

每个子域名:\w+(?:-+\w+)*匹配单词字符串以及可选的前面带有破折号的单词。

每个主机名:\s*(?:(?:\w+(?:-\w+)*\.)+[a-z]+)\s*一堆子域名后跟一个点。然后最后只跟一串字母(tld)。当然还有两侧的可选空间。

整件事:\s*(?:(?:\w+(?:-\w+)*\.)+[a-z]+)\s*(?:,\s*(?:(?:\w+(?:-\w+)*\.)+[a-z]+)\s*)*一个主机名,后跟0个或更多,hostname个逗号分隔列表。

非常简单。

答案 1 :(得分:1)

虽然@dandavis的回答/评论令人印象深刻,但我们可以将其分解为步骤。

  1. 从textarea和trim()前导和结尾空格中获取值。
  2. 使用/\s+/g用一个空格替换所有空格。意思是找出每个空格发生一次或多次。
  3. ,<space><space>,<space>拆分。 Split返回数组。
  4. 使用过滤器
  5. 迭代每个数组元素
  6. 检查元素是否为有效域。如果是这样,请将其归还。
  7. &#13;
    &#13;
    var domains = document.querySelector("textarea").value;
    domains = domains.trim().replace(/\s+/g, " ").split(/\s?,\s/);
    
    var domainsTested = domains.filter(function(element){
                      if (element.match(/^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$/))
                        {
                          return element;
                        }
                  })
    
    document.write(domainsTested.join(" | ")); //this is just here to show the results.
    document.write("<br />Domainstring is ok: " + (domainsTested.length == domains.length)); //If it's valid then this should be equal.
    &#13;
    <textarea style="width: 300px; height: 100px">www.example.com    , example.com, example.ca,     example, example.com example.nl     www.example,    www.exam ple.com,  sub.sub.sub.domain.tv, do main.it,   sub.domain.tv</textarea>
    &#13;
    &#13;
    &#13;

答案 2 :(得分:1)

function validate() {
    //Get the user input
    var hostnames = document.getElementById('yourtextarea').value;
    //Regex to validate hostname
    var re = new RegExp(/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/);
    //Trim whitespace
    hostnames = hostnames.trim();
    //Explode into an array
    hostnames = hostnames.split(",");
    //Loop through array & test each hostname with regex
    var is_valid = true;
    for (var i=0; i < hostnames.length; i++){
        var hostname = hostnames[i].trim();
        if (re.test(hostname)) {
           is_valid = true; //if valid, continue loop
        } else {
           is_valid = false; //if invalid, break loop and return false
           break;
        }
    } //end for loop
    return is_valid;
} //end function validate()

匹配您指定的每个示例,但&#34; dom-ain.it,domain.com,domain.eu.org.something&#34;因为&#34;某事&#34;无效。

JSFiddle:http://jsfiddle.net/nesutqjf/2/

答案 3 :(得分:0)

我不会为此使用正则表达式,因为您要检查不同规则的很多。当你只有一些非常容易表达的规则但是很难写出“解析代码”时,Regexp很好。

我只是做hostnames.split(',').forEach(validateHostname);,正如大多数评论所暗示的那样,并且在validateHostname里面拒绝任何在中间有空格的主机名,两个相邻的点,没有点,以点结尾,有非ASCII字符,在最后一个以点分隔的标记中有数字,依此类推。

这样的函数比正则表达式更容易添加新规则。

答案 4 :(得分:0)

我一直在使用这种模式,似乎也适合你的情况:

/^[a-zA-Z0-9][a-zA-Z0-9\-_]*\.([a-zA-Z0-9]+|[a-zA-Z0-9\-_]+\.[a-zA-Z]+)+$/gi

逻辑很简单:

  • ^[a-zA-Z0-9]:网址必须以字母数字字符
  • 开头
  • [a-zA-Z0-9\-_]*:第一个字母数字字符后跟零个或多个字符:字母数字字符,下划线或短划线
  • \.:第一件必须跟着一段时间。
  • 第二件必须遵循相同的模式:
    1. [a-zA-Z0-9]+:一个或多个字母数字字符,或
    2. [a-zA-Z0-9\-_]+\.[a-zA-Z0-9]+:一个或多个字母数字字符,下划线或短划线,后跟句点和一个或多个字母数字字符

您可以在以下代码段中检查此模式是否适用于您的大多数网址。我是怎么做的,与其他人描述的策略类似:

  • 在keyup上获取textarea的值(或者你可以绑定提交,模糊,按键,keydown,更改等)
  • ,字符
  • 拆分值
  • 使用$.trim()删除侧翼空格
  • 使用上面的RegEx模式评估每个字符串

可选,完成视觉输出:

  • 生成网址列表
  • 表明输入的每个网址是否有效

$(function() {
    $('textarea').keyup(function() {
        var urls = $(this).val().split(',');
        $('ul').empty();
        $.each(urls, function(i,v) {
            // Trim URL
            var url = $.trim(v);
            
            // RegEx
            var pat = /^[a-zA-Z0-9][a-zA-Z0-9\-_]*\.([a-zA-Z0-9]+|[a-zA-Z0-9\-_]+\.[a-zA-Z]+)+$/gi,
                test = pat.test(url);
            
            // Append
            $('ul').append('<li>'+url+' <span>'+test+'</span></li>');
        });
    });
});
textarea {
    width: 100%;
    height: 100px;
}
ul span {
    background-color: #eee;
    display: inline-block;
    margin-left: .25em;
    padding: 0 .25em;
    text-transform: uppercase;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea placeholder="Paste URLs here"></textarea>
<ul></ul>

答案 5 :(得分:0)

validate.js的示例,其中包含经过良好测试的例程,用于测试有效的FQDN。或者查看源代码并获取所需内容。

function validate (e) {
    var target = e.target || e;
    
    target.value.split(',').some(function (item) {
        var notValid = !validator.isFQDN(item.trim());
        
        if (notValid) {
            target.classList.add('bad');
        } else {
            target.classList.remove('bad');
        }
      
      return notValid;
    });
}

var domains = document.getElementById('domains');

domains.addEventListener('change', validate);

validate(domains);
#domains {
    width: 300px;
    height: 100px;
}
.bad {
    background-color: red
}
<script src="http://rawgit.com/chriso/validator.js/master/validator.js"></script>
<textarea id="domains">www.example.com, example.com, example.ca, example, example.com example.nl www.example, www.exam ple.com</textarea>