求一段javascript正则表达式,100分

发布网友 发布时间:2022-04-23 17:02

我来回答

5个回答

懂视网 时间:2022-05-15 02:13

这次给大家带来如何使用JS正则命名,使用JS正则命名的注意事项有哪些,下面就是实战案例,一起来看一下。

前言

以往我们只是习惯于通过数组下标来访问正则匹配到的分组,但分组达到4、5个时,标识起来就会非常麻烦。V8早已实现了正则命名分组提案,只是我们很少使用,本文将介绍JS的正则命名分组。

以往的做法

假设要使用正则匹配一个日期的年月日,以往我们会这样做:

const RE_DATE = /(d{4})-(d{2})-(d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

这里有几个缺点:

  • 要找到一个分组的位置,你必须要去数括号的位置,有时嵌套起来会更令人头疼。

  • 后面维护代码的同学阅读起来,还要根据下标找到正则里面对应的括号,并且要再次阅读括号里面的正则才知道含义。

  • 当你调整正则捕获分组的数量、顺序或嵌套时,你必要还要对下面的代码做调整。

  • 所有这些问题,都可以通过正则命名分组来解决。

    现在的玩法

    现在你只需要给分组里面一个命名标识即可:

    (?<year>d{4})

    这里,我们用变量year标记了上一个捕获组#1。 该名称必须是合法的JavaScript标识符。 匹配后,您可以通过matchObj.groups.year访问捕获的字符串。

    让我们通过命名分组重写前面的代码:

    const RE_DATE = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/;
    const matchObj = RE_DATE.exec('1999-12-31');
    const year = matchObj.groups.year; // 1999
    const month = matchObj.groups.month; // 12
    const day = matchObj.groups.day; // 31

    如果正则里面有了命名分组,那么匹配结果会多了一个groups 的属性,这个属性中包含了一切命名分组的捕获结果。配合上解构大法使用又是一股清流:

    const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
    console.log(year); // 1999
    console.log(day); // 31

    当然,即使你使用了命名分组,那么返回的结果还可以通过以往的数组下标方式访问:

    const year2 = matchObj[1]; // 1999
    const month2 = matchObj[2]; // 12
    const day2 = matchObj[3]; // 31

    命名分组具有以下优点:

  • 找到分组的“ID”更容易。

  • 匹配的代码变得自描述性,因为分组的ID描述了捕获的内容。

  • 如果更改分组的顺序,则不必更改匹配的代码。

  • 分组的名称也使正则表达式更易于理解,因为您可以直接看到每个组的用途。

  • 反向引用

    反向引用命名分组k<name>

    看下面这个匹配重复单词的例子:

    const RE_TWICE = /^(?<word>[a-z]+)!k<word>$/;
    RE_TWICE.test('abc!abc'); // true
    RE_TWICE.test('abc!ab'); // false

    同时也可以使用以往的反向引用方式:

    const RE_TWICE = /^(?<word>[a-z]+)!1$/;
    RE_TWICE.test('abc!abc'); // true
    RE_TWICE.test('abc!ab'); // false

    replace( )

    字符串方法replace()以两种方式支持命名分组:

    方式一

    const RE_DATE = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/;
    console.log('1999-12-31'.replace(RE_DATE,
     '$<month>/$<day>/$<year>'));
     // 12/31/1999

    如果replace不一定是直接返回新的拼接字符串,那么可以看看下面的办法:

    方式二

    const RE_DATE = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/;
    console.log('1999-12-31'.replace(
     RE_DATE,
     (g, y, m, d, offset, input, {year, month, day}) =>
     month+'/'+day+'/'+year));
     // 12/31/1999

    看看这replace的callback形参密密麻麻看得心慌慌,很多都用不上,那么我们看看更简单的写法:

    console.log('1999-12-31'.replace(RE_DATE,
     (...args) => {
     const {year, month, day} = args.slice(-1)[0];
     return month+'/'+day+'/'+year;
     }));
     // 12/31/1999

    这里配合上spread operator直取最后一个参数,再接上一个解构大法,结果又是一股清流。

    命名分组没有匹配结果?

    如果可选的命名组不被匹配,则其属性值被设置为undefined,但key是仍存在:

    const RE_OPT_A = /^(?<as>a+)?$/;
    const matchObj = RE_OPT_A.exec('');
    // We have a match:
    console.log(matchObj[0] === ''); // true
    // Group <as> didn't match anything:
    console.log(matchObj.groups.as === undefined); // true
    // But property as exists:
    console.log('as' in matchObj.groups); // true

    异常情况

    分组名不能有重复项:

    /(?<foo>a)(?<foo>b)/ // SyntaxError: Duplicate capture group name

    反向引用一个不存在的分组名:

    /k<foo>/u // SyntaxError: Invalid named capture referenced
    /k<foo>/.test("k<foo>") // true, 非 Unicode 下为了向后兼容,k 前面的  会被丢弃

    在 reaplce() 方法的替换字符串中引用一个不存在的分组:

    "abc".replace(/(?<foo>.*)/, "$<bar>") // SyntaxError: Invalid replacement string
    "abc".replace(/(.*)/, "$<bar>") // "$<bar>",不包含命名分组时会向后兼容

    最后

  • Chrome60 已支持命名分组

  • 通过babel插件处理兼容问题

  • babel-plugin-transform-modern-regexp

    相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

    推荐阅读:

    在案例中使用vue2.0+boostrap

    vue脚手架与vue-cli安装

    从零开始操作微信小程序登录鉴权

    热心网友 时间:2022-05-14 23:21

    以前搜集了很久 全给你了

    匹配中文字符的正则表达式: [\u4e00-\u9fa5]

    匹配双字节字符(包括汉字在内):[^\x00-\xff]

    匹配空行的正则表达式:\n[\s| ]*\r

    匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

    匹配首尾空格的正则表达式:(^\s*)|(\s*$)

    匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

    匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

    (1)应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
    String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

    (2)应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现
    String.prototype.trim = function()
    {
    return this.replace(/(^\s*)|(\s*$)/g, "");
    }
    (3)应用:利用正则表达式分解和转换IP地址
    function IP2V(ip) //IP地址转换成对应数值
    {
    re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
    if(re.test(ip))
    {
    return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
    }
    else
    {
    throw new Error("Not a valid IP address!")
    }
    }

    (4)应用:从URL地址中提取文件名的javascript程序

    s="http://www.9499.net/page1.htm";
    s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2") ; //Page1.htm

    (5)应用:利用正则表达式*网页表单里的文本框输入内容

    用正则表达式*只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"
    用正则表达式*只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"
    用正则表达式*只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
    用正则表达式*只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

    ====================================================
    正则表达式大全

    正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。本贴随时会更新。

    匹配中文字符的正则表达式: [\u4e00-\u9fa5]

    匹配双字节字符(包括汉字在内):[^\x00-\xff]

    应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

    String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

    匹配空行的正则表达式:\n[\s| ]*\r

    匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

    匹配首尾空格的正则表达式:(^\s*)|(\s*$)

    应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:

    String.prototype.trim = function()
    {
    return this.replace(/(^\s*)|(\s*$)/g, "");
    }

    利用正则表达式分解和转换IP地址:

    下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的javascript程序:

    function IP2V(ip)
    {
    re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
    if(re.test(ip))
    {
    return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
    }
    else
    {
    throw new Error("Not a valid IP address!")
    }
    }

    不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

    var ip="10.100.20.168"
    ip=ip.split(".")
    alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

    匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

    匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

    利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]

    var s="abacabefgeeii"
    var s1=s.replace(/(.).*\1/g,"$1")
    var re=new RegExp("["+s1+"]","g"?琼?涡獢p?????浜睹扥潜桴牥掼极慢?瑨m?)
    var s2=s.replace(re,"")
    alert(s1+s2) //结果为:abcefgi

    我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。

    得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

    s="http://www.9499.net/page1.htm"
    s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
    alert(s)

    利用正则表达式*网页表单里的文本框输入内容:

    用正则表达式*只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

    用正则表达式*只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

    用正则表达式*只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

    用正则表达式*只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

    补充:
    ^\d+$ //匹配非负整数(正整数 + 0)
    ^[0-9]*[1-9][0-9]*$ //匹配正整数
    ^((-\d+)|(0+))$ //匹配非正整数(负整数 + 0)
    ^-[0-9]*[1-9][0-9]*$ //匹配负整数
    ^-?\d+$ //匹配整数
    ^\d+(\.\d+)?$ //匹配非负浮点数(正浮点数 + 0)
    ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ //匹配正浮点数
    ^((-\d+(\.\d+)?)|(0+(\.0+)?))$ //匹配非正浮点数(负浮点数 + 0)
    ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ //匹配负浮点数
    ^(-?\d+)(\.\d+)?$ //匹配浮点数
    ^[A-Za-z]+$ //匹配由26个英文字母组成的字符串
    ^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串
    ^[a-z]+$ //匹配由26个英文字母的小写组成的字符串
    ^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串
    ^\w+$ //匹配由数字、26个英文字母或者下划线组成的字符串
    ^[\w-]+(\.[\w?琼?涡獢p?????浜睹扥潜桴牥掼极慢?瑨m?-]+)*@[\w-]+(\.[\w-]+)+$ //匹配email地址
    ^[a-zA-z]+://匹配(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$ //匹配url

    利用正则表达式去除字串中重复的字符的算法程序:

    var s="abacabefgeeii"
    var s1=s.replace(/(.).*\1/g,"$1")
    var re=new RegExp("["+s1+"]","g")
    var s2=s.replace(re,"")
    alert(s1+s2) //结果为:abcefgi
    ===============================
    如果var s = "abacabefggeeii"
    结果就不对了,结果为:abeicfgg
    正则表达式的能力有限

    RE: totoro
    谢谢你的指点,这个javascript正则表达式程序算法确实有问题,我会试着找更好的办法!!!

    1.确认有效电子邮件格式
    下面的代码示例使用静态 Regex.IsMatch 方法验证一个字符串是否为有效电子邮件格式。如果字符串包含一个有效的电子邮件地址,则 IsValidEmail 方法返回 true,否则返回 false,但不采取其他任何操作。您可以使用 IsValidEmail,在应用程序将地址存储在数据库中或显示在 ASP.NET 页中之前,筛选出包含无效字符的电子邮件地址。

    [Visual Basic]
    Function IsValidEmail(strIn As String) As Boolean
    ' Return true if strIn is in valid e-mail format.
    Return Regex.IsMatch(strIn, ("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")
    End Function
    [C#]
    bool IsValidEmail(string strIn)
    {
    // Return true if strIn is in valid e-mail format.
    return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
    }

    2.清理输入字符串
    下面的代码示例使用静态 Regex.Replace 方法从字符串中抽出无效字符。您可以使用这里定义的 CleanInput 方法,清除掉在接受用户输入的窗体的文本字段中输入的可能有害的字符。CleanInput 在清除掉除 @、-(连字符)和 .(句点)以外的所有非字母数字字符后返回一个字符串。

    [Visual Basic]
    Function CleanInput(strIn As String) As String
    ' Replace invalid characters with empty strings.
    Return Regex.Replace(strIn, "[^\w\.@-]", "")
    End Function
    [C#]
    String CleanInput(string strIn)
    ?琼?涡獢p?????浜睹扥潜桴牥掼极慢?瑨m?{
    // Replace invalid characters with empty strings.
    return Regex.Replace(strIn, @"[^\w\.@-]", "");
    }

    3.更改日期格式
    以下代码示例使用 Regex.Replace 方法来用 dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式。

    [Visual Basic]
    Function MDYToDMY(input As String) As String
    Return Regex.Replace(input, _
    "\b(?<month>\d{1,2})/(?<day>\d{1,2})/(?<year>\d{2,4})\b", _
    "${day}-${month}-${year}")
    End Function
    [C#]
    String MDYToDMY(String input)
    {
    return Regex.Replace(input,
    "\\b(?<month>\\d{1,2})/(?<day>\\d{1,2})/(?<year>\\d{2,4})\\b",
    "${day}-${month}-${year}");
    }
    Regex 替换模式
    本示例说明如何在 Regex.Replace 的替换模式中使用命名的反向引用。其中,替换表达式 ${day} 插入由 (?<day>...) 组捕获的子字符串。

    有几种静态函数使您可以在使用正则表达式操作时无需创建显式正则表达式对象,而 Regex.Replace 函数正是其中之一。如果您不想保留编译的正则表达式,这将给您带来方便

    4.提取 URL 信息
    以下代码示例使用 Match.Result 来从 URL 提取协议和端口号。例如,“http://www.contoso.com:8080/letters/readme.html”将返回“http:8080”。

    [Visual Basic]
    Function Extension(url As String) As String
    Dim r As New Regex("^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/", _
    RegexOptions.Compiled)
    Return r.Match(url).Result("${proto}${port}")
    End Function
    [C#]
    String Extension(String url)
    {
    Regex r = new Regex(@"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/",
    RegexOptions.Compiled);
    return r.Match(url).Result("${proto}${port}");
    }

    今天有网友问:如何用正则表达式表示要么是数字要么是字母 是字母的话只能是一个字母 数字则无所谓?
    我的回答是:
    ^[a-zA-Z]$|^\d+$

    热心网友 时间:2022-05-15 00:39

    我这样写都可以啊,用IE6,FIREFOX 3.0 都试过了,没问题。
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="">
    <META NAME="Keywords" CONTENT="">
    <META NAME="Description" CONTENT="">
    </HEAD>

    <BODY>
    Xhtml Linux
    </BODY>
    <script language="JavaScript">
    document.body.innerHTML = document.body.innerHTML.replace(/(x)|(l)/gi,"<font color=red>$1$2</font>");
    </script>
    </HTML>

    以下是通过FIREFOX 3.0 得到的BODY的innerHTM
    <font color="red">X</font>htm<font color="red">l</font> <font color="red">L</font>inu<font color="red">x</font>
    <script><font color=red>l</font>anguage="JavaScript">
    document.body.innerHTM<font color=red>L</font> = document.body.innerHTM<font color=red>L</font>.rep<font color=red>l</font>ace(/(<font color=red>x</font>)|(<font color=red>l</font>)/gi,"<font co<font color=red>l</font>or=red>$1$2</font>");
    </script>

    热心网友 时间:2022-05-15 02:13

    document.body.innerHTML = document.body.innerHTML.replace(/<?php echo "$searchterm" ?>/gi, "<font color=red>$+</font>");

    ------------------------------
    下面代码我有测试过,可以呀

    <?php
    $searchterm = "x";
    ?>
    <script language="JavaScript">
    window.onload = function() {
    document.body.innerHTML = document.body.innerHTML.replace(/<?php echo "$searchterm" ?>/gi,"<font color=red>$+</font>");
    };
    </script>

    <body>

    jlj5osldfg fsx

    Xhtml

    activeX

    3idjmax

    </body>

    热心网友 时间:2022-05-15 04:05

    把正则表达式后面那个 /gi 中的 i 去掉。

    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com