Regular Expressions 101

Save & Manage Regex

  • Current Version: 1
  • Save & Share
  • Community Library

Flavor

  • PCRE2 (PHP)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java
  • .NET 7.0 (C#)
  • Rust
  • PCRE (Legacy)
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests
Sponsors
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Non-capturing group
    (?:...)
  • Capturing group
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression
Processing...

Test String

Code Generator

Generated Code

import re regex = re.compile(r"key[ :']+([^,;'\"]+)[ '\",;]+") test_str = ("<!DOCTYPE html>\n" "<!--[if lt IE 7]><html class=\"ie6 oldie\" lang=\"zh\"><![endif]-->\n" "<!--[if IE 7]><html class=\"ie7 oldie\" lang=\"zh\"><![endif]-->\n" "<!--[if IE 8]><html class=\"ie8 oldie\" lang=\"zh\"><![endif]-->\n" "<!--[if gt IE 8]><!--> <html lang=\"zh\"> <!--<![endif]-->\n" "<head>\n" "<meta http-equiv=\"X-UA-Compatible\" content=\"edge\" />\n" "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" "<meta name=\"renderer\" content=\"webkit\">\n" "<!--[if lt IE 7]>\n" "<meta http-equiv=\"refresh\" content=\"0; url=http://miwifi.com/cgi-bin/luci/web/ieblock\" />\n" "<![endif]-->\n" "<!--[if gte IE 9]>\n" "<style>\n" "body {\n" " filter: none;\n" "}\n" "</style>\n" "<![endif]-->\n" " <title>小米路由器</title>\n" " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n" " <link href=\"/xiaoqiang/web/css/bc.css?v=0.0.3\" rel=\"stylesheet\">\n" " <link href=\"/xiaoqiang/web/css/login.css?v=0.0.3\" rel=\"stylesheet\">\n" "</head>\n" "<body>\n" "<div id=\"doc\">\n" " <div id=\"hd\">\n" " </div>\n" " <div id=\"bd\">\n" " <div class=\"mod-login\">\n" " <div class=\"title\">\n" " <img src=\"/xiaoqiang/web/img/zh_cn/bg_login_tit.png?v=0.0.3\" height=\"124\">\n" " </div>\n" " <div class=\"pic\">\n" " <img src=\"/xiaoqiang/web/img/topograph/router_r3_101.png\" >\n" " </div>\n" " <div class=\"rtname\">\n" " Xiaomi_6FAC (家)\n" " </div>\n" " <form id=\"rtloginform\" name=\"rtloginform\" method=\"post\" class=\"form-login\">\n" " <div class=\"form-item\">\n" " <span class=\"v\"><input id=\"password\" class=\"ipt-text\" type=\"password\" name=\"router_password\" autocomplete=\"off\" placeholder=\"请输入路由器管理密码\" reqMsg=\"请输入路由器管理密码\"></span>\n" " <em class=\"t\"></em>\n" " </div>\n" " <div class=\"form-contral\">\n" " <a id=\"btnRtSubmit\" class=\"btn-login\"></a>\n" " </div>\n" " </form>\n" " <div class=\"mobile-ft\">\n" " <p>\n" " <a target=\"_blank\" href=\"http://www1.miwifi.com\">官方网站</a>\n" " </p>\n" " </div>\n" " </div>\n" " </div>\n" " \n" "<div id=\"ft\">\n" " <p>&copy; 2015 小米路由器<span>|</span><a href=\"http://www1.miwifi.com\" target=\"_blank\">官方网站</a><span>|</span><a href=\"http://weibo.com/xiaomiluyouqi\" target=\"_blank\">官方微博</a><span>|</span><a href=\"https://land.xiaomi.net/res/e1fdbc3/land/miwifi/wf_2dcode.jpg\" target=\"_blank\" id=\"wechatcode\">官方微信</a><span>|</span><a href=\"http://bbs.xiaomi.cn/f-354\" target=\"_blank\">用户社区</a><span>|</span><a target=\"_blank\" href=\"http://www1.miwifi.com/miwifi_faq.html\">常见问题</a><span>|</span>服务热线 400-100-5678<p>\n" "</div>\n\n" "</div>\n\n" "<!--[if lt IE 7]>\n" "<script>\n" "try{ document.execCommand(\"BackgroundImageCache\",false,true);} catch(e){}\n" "</script>\n" "<![endif]-->\n" "<div class=\"mask-menu\" id=\"maskMenu\" style=\"position:fixed;left:0;top:0; width:100%; height:100%; z-index:2; display:none;\"></div>\n" "<div id=\"dropmenu\" class=\"dropmenu\" style=\"z-index:3; display:none;\">\n" " <ul>\n" " <li><a href=\"#\" id=\"toRename\">修改路由器名称</a></li>\n" " \n" " <li><a href=\"/cgi-bin/luci/web/setting/upgrade\">系统升级</a></li>\n" " \n" " <li><a href=\"#\" id=\"toDownloadClient\">下载客户端</a></li>\n" " <li><a href=\"#\" id=\"toReboot\">重启</a></li>\n" " \n" " <li class=\"last\"><a href=\"/cgi-bin/luci/web/logout\">注销</a></li>\n" " </ul>\n" "</div>\n" "<div id=\"noticebar\" class=\"noticebar\" style=\"z-index:3; display:none;\">\n" " <i class=\"ico-arrow\"></i>\n" " <div class=\"content\"></div>\n" "</div>\n" "<script>\n" "var i18n = {};\n" "i18n.dialog = {\n" " ok: '确认',\n" " cancel: '取消',\n" " loading: '加载中...',\n" " dlgtitle: '消息框'\n" "};\n" "i18n.valid = {\n" " n_integer: '请输入一个{$0}位正整数。',\n" " n_format: '数字输入格式为&#34;{$0}&#34;。',\n" " n_upper: '输入值太大,最大允许{$0}。', //注意:{$0}表示允许值,{$1}表示实际值\n" " n_lower: '输入值太小,最小允许{$0}。',\n" " nrange_from: '您输入的范围不合理。',\n" " nrange_to: '您输入的范围不合理。',\n" " n_useless_zero: '数字前面好像有多余的&#34;0&#34;。',\n" " d_format: '日期输入格式为&#34;YYYY-MM-DD&#34;。',\n" " d_upper: '日期太晚,最晚允许{$0}。',\n" " d_lower: '日期太早,最早允许{$0}。',\n" " daterange_from: '起始日期不能大于截止日期。',\n" " daterange_to: '截止日期不能小于起始日期。',\n" " daterange_larger_span: \"时间跨度不得超过{$0}天。\",\n" " text_longer: '最多允许{$0}个字。', //'{$1}字太多,最多允许{$0}字'\n" " text_shorter: '请至少输入{$0}个字。', //'{$1}字太少,最少允许{$0}字'\n" " bytetext_longer: '最多允许{$0}个字节。', //'{$1}字节太多,最多允许{$0}字节'\n" " bytetext_shorter: '请至少输入{$0}个字节。', //'{$1}字节太少,最少允许{$0}字节'\n" " richtext_longer: '最多允许{$0}个字。',\n" " richtext_shorter: '请至少输入{$0}个字。',\n" " _reconfirm: '两次输入不一致。',\n" " _time: '请检查您输入的时间格式。',\n" " _minute: '请检查您输入的时间格式。',\n" " _email: '请检查您输入的Email格式。',\n" " _mobilecode: '请检查您输入的手机号码。',\n" " _phone: '请检查您输入的电话号码。',\n" " _phonewithext: '请检查您输入的电话号码。',\n" " _phonezone: '请检查您输入的电话区号。',\n" " _phonecode: '请检查您输入的电话号码。',\n" " _phoneext: '请检查您输入的电话分机号码。',\n" " _zipcode: '请检查您输入的邮政编码。',\n" " _idnumber: '请检查您输入的身份证号码,目前只支持15位或者18位。',\n" " _bankcard: '请检查您输入的银行账号。',\n" " _cnname: '请检查您输入的姓名。',\n" " _vcode: '请检查您输入的验证码。',\n" " _imgfile: '请检查您选择的图片文件路径,只支持jpg、jpeg、png、gif、tif、bmp格式。',\n" " _regexp: '请检查您的输入。',\n" " _magic: '请检查您的输入。',\n" " _req_text: '请填写{$0}。',\n" " _req_select: '请选择{$0}。',\n" " _req_file: '请上传{$0}。',\n" " _logicrequired: '{$0}输入不完整.',\n" " _ssid: '请输入标准字符,如 Xiaomi.Luyouqi',\n" " _macaddr: 'MAC地址格式有误,如ab:cd:ef:11:22:33',\n" " _weppassword: '密码输入有误',\n" " _wifipassword: '不能包含中文',\n" " _ipaddr: 'IP地址由4个 0~255 之间的数字组成,数字之间用点区隔',\n" " _url: '必须是完整的URL,如 http://miwifi.com'\n" "};\n" "</script>\n" "<script src=\"/js/jquery-1.8.3.js?v=0.0.3\"></script>\n" "<script src=\"/js/qwrap.js?v=0.0.3\"></script>\n" "<script src=\"/js/common.js?v=0.0.3\"></script>\n" "<script src=\"/js/raphael.js?v=0.0.3\"></script>\n" "<script src=\"/js/crypto-js/rollups/sha1.js?v=0.0.3\"></script>\n" "<script src=\"/js/crypto-js/rollups/aes.js?v=0.0.3\"></script>\n" "<script src=\"/js/valid.js?v=0.0.3\"></script>\n" "<script src=\"/xiaoqiang/web/js/selectbeautify.js?v=0.0.3\"></script>\n" "<script src=\"/xiaoqiang/web/js/jquery.dialog.js?v=0.0.3\"></script>\n" "<script src=\"/xiaoqiang/web/js/jquery.cookie.js?v=0.0.3\"></script>\n" "<script>\n" "(function(){\n" " var hardwareModel = 'R3',\n" " R1CM = hardwareModel === 'R1CM',\n" " R1CL = hardwareModel === 'R1CL',\n" " R1D = hardwareModel === 'R1D',\n" " R2D = hardwareModel === 'R2D',\n" " R3 = hardwareModel === 'R3';\n" " var G_CONFIG = {\n" " R1CM : R1CM,\n" " R1CL : R1CL,\n" " R1D: R1D,\n" " R2D: R2D,\n" " R3: R3\n" " };\n" " var G_FEATURES = $.parseJSON('{\"hardware\":{\".name\":\"hardware\",\".type\":\"features\",\"disk\":\"0\",\".index\":4,\".anonymous\":false,\"usb\":\"1\"},\"apps\":{\".name\":\"apps\",\".type\":\"features\",\"apptc\":\"0\",\".anonymous\":false,\"qos\":\"1\",\".index\":3},\"wifi\":{\".name\":\"wifi\",\".type\":\"features\",\"wifi24\":\"1\",\"wifi50\":\"1\",\"wifiguest\":\"1\",\".anonymous\":false,\".index\":1},\"apmode\":{\".name\":\"apmode\",\".type\":\"features\",\".index\":2,\"wifiapmode\":\"1\",\".anonymous\":false,\"lanapmode\":\"1\"},\"system\":{\".name\":\"system\",\".type\":\"features\",\"shutdown\":\"0\",\"i18n\":\"0\",\"downloadlogs\":\"0\",\".anonymous\":false,\".index\":0}}');\n" " window['G_CONFIG'] = G_CONFIG;\n" " window['G_FEATURES'] = G_FEATURES;\n" "}())\n" "</script>\n\n" "<script>\n" "// reboot\n" "var global_api_reboot = {\n" " url : '/cgi-bin/luci/api/xqsystem/reboot',\n" " param : {\"client\":\"web\"}\n" "};\n" "function reboot_window( needconfirm ) {\n" " console.log( needconfirm );\n" " var reboot = function(){\n" " $.getJSON( global_api_reboot.url, global_api_reboot.param, function( rsp ) {\n" " if( rsp.code !== 0 ){\n" " $.alert( rsp.msg ).time( 1.5*1000 );\n" " } else {\n" " var ip = rsp.lanIp[0].ip;\n" " rebootWait( {\n" " lanIp : ip,\n" " action : '重启路由器',\n" " refresh : true\n" " } );\n" " }\n" " });\n" " };\n" " if ( typeof( needconfirm ) !== \"undefined\" && needconfirm === false ) {\n" " reboot();\n" " return;\n" " }\n" " $.confirm('确定重启路由器,重启将断开和小米路由器的连接。',function () {\n" " var dlg = this;\n" " reboot();\n" " dlg.close();\n" " return false;\n" " });\n" "}\n" "// shutdown\n" "function shutdown_window(){\n" " $.confirm('是否确定关闭路由器,操作将断开和小米路由器的连接。', function () {\n" " $.getJSON( '/cgi-bin/luci/api/xqsystem/shutdown', {}, function( rsp ){\n" " if( rsp.code !== 0 ){\n" " $.alert(rsp.msg).time( 1.5*1000 );\n" " } else {\n" " $.loadingDialog({\n" " title: '关闭路由器',\n" " content: '关机中,请等待路由器指示灯熄灭后再断开电源'\n" " });\n" " }\n" " });\n" " });\n" "}\n" "//reset\n" "function reset_window( format ){\n\n" " var reset = (function( format ){\n" " var requestURL = '/cgi-bin/luci/api/xqsystem/reset',\n" " requestData = {\n" " format: format ? 1 : 0\n" " },\n" " wait = function(){\n" " rebootWait( {\n" " action : '恢复出厂设置',\n" " refresh : true,\n" " lanIp: '192.168.31.1'\n" " } );\n" " },\n" " clearCookies = function (){\n" " var keys = document.cookie.match(/[^ =;]+(?=\\=)/g);\n" " if ( keys ) {\n" " for (var i = keys.length; i--;){\n" " document.cookie = keys[i]+'=0;path=/;expires=' + new Date(0).toUTCString();\n" " }\n" " }\n" " };\n\n" " return function(){\n" " $.getJSON( requestURL , requestData, function( rsp ) {\n" " if ( rsp.code !== 0 ) {\n" " $.alert( rsp.msg ).time( 3*1000 );\n" " }else{\n" " // clear cookies\n" " clearCookies();\n" " //block wait\n" " wait();\n" " }\n" " });\n" " }\n" " })( format );\n\n" " $.confirm('确定要恢复出厂设置让小米路由器回到初始状态?', function(){\n" " reset();\n" " });\n" "}\n" "</script>\n" "<script type=\"text/tmpl\" id=\"tplrename\">\n" "<div class=\"mod-rename-dlg\">\n" " <p class=\"img\"><img src=\"/xiaoqiang/web/img/topograph/router_r3_101.png\"></p>\n" " <div class=\"form-rename\">\n" " <form action=\"#\" class=\"form\" id=\"routerNameEdit\">\n" " <div class=\"form-item\">\n" " <label class=\"k\">路由器名称</label>\n" " <span class=\"v\">\n" " <input type=\"text\" name=\"routername\" id=\"routername\" class=\"ipt-text\" autocomplete=\"off\" datatype=\"bytetext\" maxlength=\"24\" reqMsg=\"路由器名称\" value=\"{$name}\">\n" " </span>\n" " <em class=\"t\"></em>\n" " </div>\n" " <div class=\"form-item\">\n" " <label class=\"k\">位置</label>\n" " <span class=\"v\">\n" " <input type=\"text\" name=\"locale\" id=\"locale\" class=\"ipt-text\" autocomplete=\"off\" datatype=\"bytetext\" maxlength=\"24\" reqMsg=\"路由器位置\" value=\"{$locale}\">\n" " </span>\n" " <em class=\"t\"></em>\n" " </div>\n" " <div class=\"form-contral\">\n" " <button type=\"submit\" class=\"btn btn-primary btn-l\"><span>保存</span></button>\n" " </div>\n" " </form>\n" " </div>\n" "</div>\n" "</script>\n" "<script type=\"text/tmpl\" id=\"tplshutdown\">\n" "<div class=\"mod-reboot-dlg\">\n" " <p class=\"img\"><img src=\"/xiaoqiang/web/img/ico_shutdown.png\"></p>\n" " <p class=\"text\">关闭路由器将断开其他设备的数据访问和网络连接,之后便可以安全的断开电源。(再次启动需要手工连接电源)</p>\n" " <button id=\"shutdownAction\" type=\"button\" class=\"btn btn-primary btn-l\"><span>关闭路由器</span></button>\n" "</div>\n" "</script>\n" "<script type=\"text/tmpl\" id=\"tplreboot\">\n" "<div class=\"mod-shutdown-dlg\">\n" " <p class=\"img\"><img src=\"/xiaoqiang/web/img/ico_reboot.png\"></p>\n" " <p class=\"text\">路由器重启需要等待十几秒或更多时间,重启过程中将会断开网络连接,稍后将自动重新连接网络。</p>\n" " <button type=\"button\" id=\"rebootAction\" class=\"btn btn-primary btn-l\"><span>重启路由器</span></button>\n" "</div>\n" "</script>\n" "<script type=\"text/tmpl\" id=\"tpldownloadclient\">\n" "<div class=\"mod-downloadclient-dlg\">\n" " <table>\n" " <tr>\n" " <td>\n" " <i class=\"ico-down-client ico-down-pc\"></i>\n" " <a href=\"http://bigota.miwifi.com/xiaoqiang/client/xqpc_client.exe\">PC客户端</a>\n" " </td>\n" " <td class=\"c1\"></td>\n" " <td class=\"c2\"></td>\n" " <td>\n" " <i class=\"ico-down-client ico-down-mac\"></i>\n" " <a href=\"http://bigota.miwifi.com/xiaoqiang/client/xqmac_client.dmg\">MAC客户端</a>\n" " </td>\n" " </tr>\n" " <tr class=\"last\">\n" " <td>\n" " <i class=\"ico-down-client ico-down-andriod\"></i>\n" " \n" " <a href=\"http://bigota.miwifi.com/xiaoqiang/client/xqapp_dev.apk\">Android客户端</a>\n" " <img class=\"onlineimg\" src-local=\"/xiaoqiang/web/img/2dcode.png\" src=\"http://www1.miwifi.com/statics/img/wf_2dcode_an_dl_dev.png\">\n" " \n" " </td>\n" " <td class=\"c1\"></td>\n" " <td class=\"c2\"></td>\n" " <td>\n" " <i class=\"ico-down-client ico-down-iphone\"></i>\n" " <a href=\"https://itunes.apple.com/cn/app/id859962702?mt=8&ls=1\">iPhone客户端</a>\n" " <img class=\"onlineimg\" src-local=\"/xiaoqiang/web/img/2dcode.png\" src=\"http://www1.miwifi.com/statics/img/wf_2dcode_ios_dl.png\">\n" " </td>\n" " </tr>\n" " </table>\n" "</div>\n" "</script>\n" "<script>\n" "var DEBUG = false;\n" "if ( !window.console || DEBUG == false) {\n" " window.console = {\n" " log: function(){}\n" " };\n" "}\n\n" "var Encrypt = {\n" " key: 'a2ffa5c9be07488bbb04a3a47d3c5f6a',\n" " iv: '64175472480004614961023454661220',\n" " nonce: null,\n" " init: function(){\n" " var nonce = this.nonceCreat();\n" " this.nonce = nonce;\n" " return this.nonce;\n" " },\n" " nonceCreat: function(){\n" " var type = 0;\n" " var deviceId = '30:65:ec:3b:e2:9a';\n" " var time = Math.floor(new Date().getTime() / 1000);\n" " var random = Math.floor(Math.random() * 10000);\n" " return [type, deviceId, time, random].join('_');\n" " },\n" " oldPwd : function(pwd){\n" " return CryptoJS.SHA1(this.nonce + CryptoJS.SHA1(pwd + this.key).toString()).toString();\n" " },\n" " newPwd: function(pwd, newpwd){\n" " var key = CryptoJS.SHA1(pwd + this.key).toString();\n" " key = CryptoJS.enc.Hex.parse(key).toString();\n" " key = key.substr(0, 32);\n" " key = CryptoJS.enc.Hex.parse(key);\n" " var password = CryptoJS.SHA1(newpwd + this.key).toString();\n" " var iv = CryptoJS.enc.Hex.parse(this.iv);\n" " var aes = CryptoJS.AES.encrypt(\n" " password,\n" " key,\n" " {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }\n" " ).toString();\n" " return aes;\n" " }\n" "};\n\n" "var pingRouter = function( on, off, ip ){\n" " var online = on || function(){},\n" " offline = off || function(){},\n" " host = ip || location.host,\n" " imgUrl = 'http://' + host + '/xiaoqiang/web/img/logo.png',\n" " time = 5000,\n" " timecounter = 0,\n" " img = null,\n" " wait = function(){\n" " console.log('pingRouter:wait');\n" " offline();\n" " },\n" " done = function(){\n" " console.log('pingRouter:done');\n" " window.clearInterval( timer );\n" " online();\n" " },\n" " loadImg = function( onload, onerror ){\n" " img = new Image();\n" " img.onload = onload;\n" " img.onerror = onerror;\n" " img.src = imgUrl+'?' + (+new Date());\n" " },\n" " timer = window.setInterval(function() {\n\n" " if ( 'onLine' in navigator ) {\n" " if ( navigator.onLine ) {\n" " loadImg(\n" " function(){\n" " done();\n" " }, function(){\n" " wait();\n" " }\n" " );\n" " } else {\n" " wait();\n" " }\n" " }else{\n" " loadImg(function(){\n" " done();\n" " }, function(){\n" " wait();\n" " });\n" " }\n" " }, time );\n" "};\n\n" "var rebootWait = function ( opt ) {\n" " var action = opt.action,\n" " ip = opt.lanIp || window.location.host,\n" " refresh = opt.refresh || false,\n" " tStart = ( +new Date() ),\n" " tUse,\n" " dlgRebootWait = $.loadingDialog({\n" " title : '重启中...',\n" " content : action + '操作生效,等待设备重启...'\n" " }),\n" " online = function(){\n" " dlgRebootWait.content( '操作生效,重启成功!' );\n" " dlgRebootWait.time( 3*1000 );\n" " if( refresh ){\n" " window.setTimeout( 'window.top.location.href=\"http://'+ip+'\";',3000 );\n" " }\n" " },\n" " offline = function(){\n" " tUse = Math.round( ( ( +new Date() ) - tStart ) / 1000 );\n" " if ( tUse > 150 ) {\n" " dlgRebootWait.content( '自动连接路由器失败,请检查无线或者网线是否连接正确。' );\n" " return;\n" " }\n" " dlgRebootWait.content( action + ', 等待自动跳转... 用时{$time}秒'.tmpl({time: tUse}) );\n" " };\n\n" " window.setTimeout( function(){\n" " pingRouter( online, offline, ip );\n" " }, 1000 * 60 );\n" "};\n\n" "(function( $ ){\n\n" " function formInit( container ) {\n" " var clsInput = 'form-item form-item-input',\n" " clsEmpty = 'form-item form-item-empty',\n" " clsDisabled = 'form-item-disabled',\n" " clsError = 'form-item-err',\n" " clsPassword = 'form-item-pwd';\n\n" " container = container || 'body';\n" " $(container).find( '.form-item input' ).each(function(){\n" " var me = this,\n" " $me = $( me ),\n" " parent = $( me.parentNode.parentNode ),\n" " label = parent.find( '.k' ),\n" " offsetX = $me.position().left;\n" " if ( !( this.type == 'text' || this.type == 'password' ) ) {\n" " return;\n" " }\n" " // some input do not need init\n" " if ($me.hasClass('no-init')) {\n" " return;\n" " }\n" " if ( me.value !=='' ) {\n" " parent[0].className = clsInput;\n" " } else {\n" " parent[0].className = clsEmpty;\n" " if ( offsetX > 0 ) {\n" " label.css({ 'left': offsetX + 10 });\n" " }\n" " }\n" " if ( me.disabled ) {\n" " parent.addClass( clsDisabled );\n" " }\n" " if ( $me.attr('data-type') === 'password' ) {\n" " parent.addClass( clsPassword );\n" " parent.append( '<i class=\"bt-showpwd bt-showpwd-off\"></i>' );\n" " }\n\n" " label.on( 'click', function(e){\n" " try {\n" " me.focus();\n" " } catch ( ex ) {}\n" " });\n\n" " });\n" " var focusHandler = function(){\n" " if ( !( this.type == 'text' || this.type == 'password' ) ) {\n" " return;\n" " }\n" " var me = $( this ),\n" " parent = $( this.parentNode.parentNode ),\n" " label = parent.find( '.k' ),\n" " t = parent.find( '.t' ),\n" " classname;\n" " if (me.hasClass('no-init')) {\n" " return;\n" " }\n" " if ( parent.hasClass( clsPassword ) ) {\n" " classname = clsInput + ' ' + clsPassword;\n" " } else {\n" " classname = clsInput;\n" " }\n" " if ( parent.hasClass( clsError ) ) {\n" " t.hide();\n" " }\n" " label.css({ 'left': 'auto' });\n" " label.hide();\n" " parent[0].className = classname;\n" " };\n" " var blurHandler = function(){\n" " var me = this,\n" " $me = $( me ),\n" " parent = $( me.parentNode.parentNode ),\n" " classname,\n" " label = parent.find( '.k' ),\n" " offsetX = $me.position().left;\n" " if ( !( this.type == 'text' || this.type == 'password' ) ) {\n" " return;\n" " }\n" " if ($(this).hasClass('no-init')) {\n" " return;\n" " }\n" " label.show();\n" " if ( me.value == '' ) {\n" " if ( parent.hasClass( clsPassword ) ) {\n" " classname = clsEmpty + ' ' + clsPassword;\n" " } else {\n" " classname = clsEmpty;\n" " }\n" " if ( offsetX > 0 ) {\n" " label.css({ 'left': offsetX + 10 });\n" " } else {\n" " label.css({ 'left': 12 });\n" " }\n" " parent[0].className = classname;\n" " }\n" " };\n" " function addInputEvent() {\n" " $(container).find( '.form-item input' )\n" " .on( 'focus', focusHandler )\n" " .on( 'blur', blurHandler );\n" " };\n\n" " function delInputEvent() {\n" " $(container).find( '.form-item input' ).off( 'focus', focusHandler );\n" " $(container).find( '.form-item input' ).off( 'blur', blurHandler );\n" " };\n" " // del password event\n" " $( 'body' ).undelegate( '.bt-showpwd', 'click' );\n" " $( 'body' ).delegate( '.bt-showpwd', 'click', function(e) {\n" " console.log( 'showpwd' );\n" " var me = this,\n" " meclass = 'bt-showpwd',\n" " formItem = $(this).closest('.form-item'),\n" " input = formItem.find('input'),\n" " inputValue = input.val(),\n" " inputWrap = formItem.find('.v'),\n" " newinput = '',\n" " inputHTML = inputWrap.html();\n\n" " if( input.attr('type') == 'password' ){\n" " newinput = inputHTML.replace( /type\\s*=\\s*('|\")?password('|\")?/ig, 'type=\"text\"');\n" " inputWrap.html( newinput ).find('input')[0].value = inputValue;\n" " me.className = meclass + ' bt-showpwd-on';\n" " }else{\n" " newinput = inputHTML.replace( /type\\s*=\\s*('|\")?text('|\")?/ig, 'type=\"password\"');\n" " inputWrap.html( newinput ).find('input')[0].value = inputValue;\n" " me.className = meclass + ' bt-showpwd-off';\n" " }\n\n" " setTimeout( function() {\n" " delInputEvent();\n" " addInputEvent();\n" " }, 0 );\n" " });\n\n\n\n" " addInputEvent();\n" " }\n\n" " $.formInit = formInit;\n\n" "})(jQuery);\n\n" "/**\n" "* byte format\n" "*/\n" "function byteFormat(number, precision, isarray){\n" " var val,\n" " label,\n" " ret;\n" " precision = precision || 100,\n" " isarray = isarray || false;\n" " if (number > 1024 * 1024 * 1024) {\n" " val = Math.floor( number / 1024 / 1024 / 1024 * precision ) / precision;\n" " label = 'GB';\n" " } else if (number > 1024 * 1024 && number < 1024 * 1024 * 1024){\n" " val = Math.floor( number / 1024 / 1024 * precision ) / precision;\n" " label = 'MB';\n" " }else{\n" " val = Math.floor( number / 1024 * precision ) / precision;\n" " label = 'KB';\n" " }\n\n" " if (isarray) {\n" " ret = [val, label];\n" " }else{\n" " ret = val + label;\n" " }\n\n" " return ret;\n" "}\n\n\n" "function secondToHour(time){\n" " var pint = function(num){\n" " return parseInt(num, 10);\n" " },\n" " hour = pint(time / 3600.0),\n" " minute = pint((parseFloat(time / 3600.0) - hour) * 60),\n" " second = pint(time) - hour * 3600 - minute * 60,\n" " format = hour + '小时' + minute + '分' + second + '秒';\n" " return format;\n" "}\n\n" "function secondToDate(second) {\n" " var time = parseFloat(second),\n" " pint = function(num){\n" " return parseInt(num, 10);\n" " },\n" " day;\n" " if (time !== null && time !== \"\") {\n" " if (time > 60 && time < 60 * 60) {\n" " time = pint(time / 60.0) + '分' + pint((parseFloat(time / 60.0) - pint(time / 60.0, 10)) * 60) + '秒';\n" " }\n" " else if (time >= 60 * 60 && time < 60 * 60 * 24) {\n" " time = secondToHour(time);\n" " }else if (time >= 24* 60 * 60 ) {\n" " day = pint(time / (3600.0 * 24) );\n" " time = time - (day * 3600 * 24);\n" " time = day + '天 ' + secondToHour(time);\n" " }\n" " else {\n" " time = pint(time) + '秒';\n" " }\n" " }\n" " return time;\n" "}\n\n" "(function( $ ){\n" " function pint(num){\n" " return parseInt(num, 10);\n" " }\n\n" " function secondToHour(time){\n" " var hour = pint(time / 3600.0),\n" " minute = pint((parseFloat(time / 3600.0) - hour) * 60),\n" " second = pint(time) - hour * 3600 - minute * 60,\n" " format = hour + '小时' + minute + '分' + second + '秒';\n" " return format;\n" " }\n\n" " function secondToDate(second) {\n" " var time = parseFloat(second),\n" " day;\n" " if (time !== null && time !== \"\") {\n" " if (time > 60 && time < 60 * 60) {\n" " time = pint(time / 60.0) + '分' + pint((parseFloat(time / 60.0) - pint(time / 60.0, 10)) * 60) + '秒';\n" " }\n" " else if (time >= 60 * 60 && time < 60 * 60 * 24) {\n" " time = secondToHour(time);\n" " }else if (time >= 24* 60 * 60 ) {\n" " day = pint(time / (3600.0 * 24) );\n" " time = time - (day * 3600 * 24);\n" " time = day + '天' + secondToHour(time);\n" " }\n" " else {\n" " time = pint(time) + '秒';\n" " }\n" " }\n" " return time;\n" " }\n\n" " function secondToDate2(second) {\n" " var time = parseFloat(second),\n" " num = 0,\n" " unit = '天';\n" " console.log( second, time );\n" " if (!isNaN(time)) {\n" " if (time > 60 && time < 60 * 60) {\n" " num = Math.floor(time / 60.0);\n" " unit = '分钟';\n" " } else if (time >= 60 * 60 && time < 60 * 60 * 24) {\n" " num = Math.floor(time / 3600.0);\n" " unit = '小时'\n" " } else if (time >= 24 * 60 * 60 ) {\n" " num = Math.floor( time / (3600.0 * 24) );\n" " unit = '天';\n" " } else {\n" " num = Math.floor(time);\n" " unit = '秒';\n" " }\n" " }\n" " return {\n" " num: num,\n" " unit: unit\n" " };\n" " }\n\n" " $.secondToHour = secondToHour;\n" " $.secondToDate = secondToDate;\n" " $.secondToDate2 = secondToDate2;\n" "})( jQuery );\n\n\n" "$( document ).ajaxSuccess( function( event, xhr, settings ) {\n" " var rsp = xhr.responseText;\n" " rsp = $.parseJSON( rsp );\n" " // console.log(event, xhr, settings);\n" " var ignore = [\n" " 'api\\/xqsystem\\/login',\n" " 'api\\/xqsystem\\/upgrade_rom'\n" " ];\n" " for (var i = 0; i < ignore.length; i++) {\n" " var ignoreTest = new RegExp(ignore[i]);\n" " // console.log( ignoreTest );\n" " if ( ignoreTest.test( settings.url ) ) {\n" " return;\n" " }\n" " }\n" " if ( rsp.code === 401 || rsp.code === 403) {\n" " document.location.href = 'http://' + location.host;\n" " }\n" "} );\n\n" "$.sub( 'wait', function( evt, data ){\n" " var selector = data.id;\n" " if ( !$.waitStatus) {\n" " $.waitStatus = {};\n" " }\n" " $.waitStatus[selector] = $( selector ).text();\n" " $( selector ).addClass('btn-primary-disabled').prop( 'disabled' , true ).find('span').text( '处理中...' );\n" "} );\n\n" "$.sub( 'done', function( evt, data ){\n" " var selector = data.id,\n" " text = $.waitStatus[selector];\n" " $( selector ).removeClass('btn-primary-disabled').prop( 'disabled' , false ).find('span').text( text );\n" "} );\n\n" "$.sub( 'loading:start', function(){\n" " var isLoading = $('html').hasClass('isloading');\n" " if ( isLoading ) {\n" " return;\n" " }\n" " var tplMask = '<div id=\"panel-loading-mask\" class=\"panel-mask\" style=\"position:fixed;left:0;top:0;style:none;\"></div>',\n" " tplLoading = ''\n" " +'<div id=\"panel-loading\" class=\"panel-loading\" style=\"style:none;\">'\n" " + '<img src=\"/img/loading2.gif\">'\n" " +'</div>',\n" " $mask = $( tplMask ),\n" " $loading = $( tplLoading ),\n" " zIndex = 10000;\n" " $mask.css({\n" " 'z-index': zIndex,\n" " width: $(window).width() + 'px',\n" " height: $(window).height() + 'px'\n" " });\n" " $loading.css({'z-index': zIndex + 1});\n" " $mask.appendTo( document.body ).show();\n" " $loading.appendTo( document.body ).show();\n" " $('html').addClass('isloading');\n" "} );\n\n" "$.sub( 'loading:stop', function(){\n" " $('html').removeClass('isloading');\n" " $('#panel-loading, #panel-loading-mask').remove();\n" "});\n\n" "// dialog block loading\n" "(function( $ ){\n" " $.loadingDialog = function( config ){\n" " var mix = ObjectH.mix,\n" " _config = config || {\n" " title: '',\n" " content: ''\n" " },\n" " conf = mix( _config, {\n" " width: 390,\n" " padding:'25px 30px',\n" " title: config.title,\n" " content: '<p style=\"padding-bottom:30px;\">{$content}</p><div class=\"loading-bar\"></div>'.tmpl({content: config.content}),\n" " cancel: false\n" " }, true ),\n" " dialog = $.dialog( conf );\n\n" " var oldcontent = dialog.content;\n" " dialog.content = function( cont ){\n" " var _cont = '<p style=\"padding-bottom:30px;\">{$content}</p><div class=\"loading-bar\"></div>'.tmpl({content: cont});\n" " return oldcontent.call( dialog, _cont);\n" " };\n" " return dialog;\n" " }\n" "})(jQuery);\n\n" "// dialog alert\n" "(function( $ ){\n" " $.alert = function( content, ok ){\n" " ok = ok || function(){};\n" " return $.dialog({\n" " width: 390,\n" " padding:'25px 30px',\n" " title: '提示信息',\n" " content: content,\n" " ok: ok,\n" " cancel: false\n" " });\n" " }\n" "})(jQuery);\n\n" "// dialog confirm\n" "(function( $ ){\n" " $.confirm = function( content, ok, cancel ){\n" " var _cancel = cancel || function(){};\n" " return $.dialog({\n" " width: 390,\n" " padding:'25px 30px',\n" " title: '确认信息',\n" " content: content,\n" " ok: ok,\n" " cancel: _cancel,\n" " lock: true\n" " });\n" " }\n" "})(jQuery);\n\n" "// wechat code dialog\n" "$(function(){\n" " $( '#wechatcode' ).click(function( e ){\n" " e.preventDefault();\n" " var $this = $( this ),\n" " href = $this.attr( 'href' );\n" " $.dialog({\n" " title: '官方微信',\n" " content: '<img width=\"200\" src=\"'+ href +'\">',\n" " width: 250,\n" " lock: true\n" " });\n" " });\n" "});\n\n\n" "// set sys language\n" "(function($){\n" " $.i18nSet = function( el ){\n" " var $lan = $( el ),\n" " apiGetLan = '/cgi-bin/luci/api/xqsystem/get_languages',\n" " apiSetlan = '/cgi-bin/luci/api/xqsystem/set_language',\n" " dtd = $.Deferred();\n\n" " $.get(apiGetLan, function( rsp ){\n" " var rsp = $.parseJSON( rsp );\n" " var selectContent = [];\n" " if ( rsp.code == 0 ) {\n" " for (var i = 0; i < rsp.list.length; i++) {\n" " var item = rsp.list[i],\n" " selected = item.lang == rsp.lang ? 'selected' : '',\n" " option = '<option value=\"' + item.lang + '\" '+ selected +'>' + item['name'] + '</option>';\n" " // clear old conf en item\n" " if ( item.lang != 'en') {\n" " selectContent.push(option);\n" " }\n" " };\n" " $lan.html( selectContent.join('') );\n" " dtd.resolve();\n" " }\n" " });\n\n" " $lan.on('change', function( e ){\n" " var el = this,\n" " val = $(this).val();\n" " $.pub('loading:start');\n" " $.post(apiSetlan, {language: val}, function( rsp ){\n" " var rsp = $.parseJSON( rsp );\n" " if ( rsp.code == 0 ) {\n" " location.reload( 1 );\n" " } else {\n" " $.alert( rsp.msg );\n" " }\n" " $.pub('loading:stop');\n" " });\n" " });\n\n" " return dtd.promise();\n" " };\n" "}(jQuery));\n\n\n\n" "// global event\n" "(function($){\n" " var dlgReboot,\n" " dlgShutdown,\n" " dlgRouterName;\n" " function getNotice(){\n" " $.getJSON('/cgi-bin/luci/api/misystem/messages', function(rsp){\n" " if ( rsp.code == 0 ) {\n" " var classname;\n" " if ( rsp.count > 0 ) {\n" " classname = 'ico-notice-new';\n" " } else {\n" " classname = 'ico-notice';\n" " }\n" " $('#sysnotice')[0].className = classname;\n" " var msgMap = {\n" " '1': '<p>检测到最新版本为{$version},<a href=\"/cgi-bin/luci/web/setting/upgrade\">点击此处立即升级</a>。</p>',\n" " '3': '<p>5G Wi-Fi启动失败,<a target=\"_blank\" href=\"http://www.mi.com/service/contact/\">请联系小米客服解决</a></p>',\n" " '4': '<p>检测到与上级路由器存在IP冲突,建议切换到<a href=\"/cgi-bin/luci/web/setting/wan#netmode\">有线中继模式</a>或者<a href=\"#\" id=\"ipconflict\" data-ip=\"{$ip}\">避让IP冲突</p>'\n" " };\n" " var msgHTML = [];\n" " for (var i = rsp.messages.length - 1; i >= 0; i--) {\n" " msgHTML.push(msgMap[rsp.messages[i].type].tmpl(rsp.messages[i].data));\n" " };\n" " $('#noticebar .content').html( msgHTML.join('') );\n\n" " if ( rsp.count > 0 ) {\n" " $('#sysnotice').trigger('click');\n" " }\n" " }\n" " });\n" " }\n" " function reNameHandler(e){\n" " e.preventDefault();\n" " $.getJSON('/cgi-bin/luci/api/misystem/router_name')\n" " .done(function( rsp ){\n" " if ( rsp.code == 0 ) {\n" " var html = StringH.tmpl($('#tplrename').html() , {\n" " locale: StringH.encode4HtmlValue(rsp.locale),\n" " name: StringH.encode4HtmlValue(rsp.name)\n" " });\n" " dlgRouterName = $.dialog({\n" " width: 390,\n" " title: '修改路由器名称',\n" " content: html,\n" " lock: true\n" " });\n" " setTimeout(function(){\n" " $.formInit('.mod-rename-dlg');\n" " $.selectBeautify({container: '.mod-rename-dlg'});\n" " }, 100);\n" " }\n" " });\n" " }\n" " function downloadClientHandler(e){\n" " e.preventDefault();\n" " $.dialog({\n" " width: 390,\n" " title: '下载客户端',\n" " content: $('#tpldownloadclient').html(),\n" " lock: true\n" " });\n" " setTimeout(function(){\n" " $('.onlineimg').each(function(){\n" " var img = new Image();\n" " var el = this;\n" " var remote = el.src;\n" " var local = $(el).attr('src-local');\n" " img.onerror = function(){\n" " el.src = local;\n" " }\n" " img.src = remote;\n" " });\n" " }, 100);\n" " }\n" " function rebootHandler(e){\n" " e.preventDefault();\n" " dlgReboot = $.dialog({\n" " width: 390,\n" " title: '重启路由器',\n" " content: $('#tplreboot').html(),\n" " lock: true\n" " });\n" " }\n" " function shutdownHandler(e){\n" " e.preventDefault();\n" " dlgShutdown = $.dialog({\n" " width: 390,\n" " title: '路由器关机',\n" " content: $('#tplshutdown').html(),\n" " lock: true\n" " });\n" " }\n\n" " function noticeHandler(e){\n" " e.preventDefault();\n" " var that = this,\n" " $this = $(this),\n" " pos = $('#userbar').position(),\n" " right,\n" " wt = 1160,\n" " wwt = $(window).width(),\n" " $arrow = $('#noticebar .ico-arrow');\n" " if ( $this.hasClass('ico-notice-new') ) {\n" " // right = wt - pos.left - 20;\n" " $arrow.css({'right': '10px'});\n" " $('#noticebar').css({'right': (wwt - wt) /2 });\n" " $('#noticebar').toggle();\n" " }\n" " $('#maskMenu').height($(window).height());\n" " $('#maskMenu').show();\n" " }\n\n" " function sysmenuHandler(e){\n" " e.preventDefault();\n" " var that = this,\n" " $this = $(this);\n" " if ( $this.hasClass('s-dropdown') ){\n" " var ww = $(window).width();\n" " // var rt = (ww - 1160) / 2;\n" " var lt = $this.offset().left + $this.outerWidth() - $('#dropmenu').width();\n" " $('#dropmenu').css({left: lt});\n" " $('#dropmenu').show();\n" " that.className = 'name s-dropup';\n" " }else{\n" " $('#dropmenu').hide();\n" " that.className = 'name s-dropdown';\n" " }\n" " $('#maskMenu').height($(window).height());\n" " $('#maskMenu').show();\n" " }\n\n" " function maskHandler(e){\n" " e.preventDefault();\n" " $('#noticebar').hide();\n" " $('#dropmenu').hide();\n" " $('#maskMenu').hide();\n" " $('#sysmenu')[0].className = 'name s-dropdown';\n" " }\n\n" " $(function(){\n" " // notice\n" " $('#sysnotice').click(noticeHandler);\n" " // user dropmenu\n" " $('#sysmenu').click(sysmenuHandler);\n" " // space click\n" " $('#maskMenu').click(maskHandler);\n" " // rename\n" " $( 'body' ).delegate( '#toRename', 'click', reNameHandler );\n" " // toDownloadClient\n" " $( 'body' ).delegate( '#toDownloadClient', 'click', downloadClientHandler );\n" " // toReboot\n" " $( 'body' ).delegate( '#toReboot', 'click', rebootHandler );\n" " // toShutdown\n" " $( 'body' ).delegate( '#toShutdown', 'click', shutdownHandler);\n\n" " $( 'body' ).delegate( '#shutdownAction', 'click', function( e ){\n" " e.preventDefault();\n" " dlgShutdown.close();\n" " shutdown_window();\n" " } );\n\n" " $( 'body' ).delegate( '#rebootAction', 'click', function( e ){\n" " e.preventDefault();\n" " dlgReboot.close();\n" " reboot_window();\n" " } );\n\n" " $( 'body' ).delegate( '#routerNameEdit', 'submit', function( e ){\n" " e.preventDefault();\n" " var validator = Valid.checkAll( this );\n" " var routername = $('#routername').val();\n" " var locale = $('#locale').val();\n" " if ( validator ) {\n" " $.getJSON('/cgi-bin/luci/api/misystem/set_router_name',{\n" " name: routername,\n" " locale: locale\n" " }).done(function(rsp){\n" " if ( rsp.code == 0 ) {\n" " location.reload(1);\n" " } else {\n" " $.alert( rsp.msg )\n" " }\n" " });\n" " }\n" " } );\n\n" " $( 'body' ).delegate('#ipconflict', 'click', function(e){\n" " e.preventDefault();\n" " var api = '/cgi-bin/luci/api/misystem/r_ip_conflict',\n" " ip = $(this).attr('data-ip');\n" " $.dialog({\n" " title: '避让IP冲突',\n" " content: '执行此操作,局域网IP将会变更为' + ip + '<br>' +'该过程无线网络会重启,将出现短暂掉线。',\n" " lock: true,\n" " ok: function(){\n" " $.post(api, function(rsp){\n" " rsp = $.parseJSON(rsp);\n" " if (rsp.code !== 0) {\n" " alert(rsp.msg);\n" " }\n" " });\n" " },\n" " cancel: function(){}\n" " });\n" " });\n\n" " // user logined and has global header get notice\n" " if ( typeof(GLOBALHEADER) !== 'undefined' && GLOBALHEADER === true ) {\n" " getNotice();\n" " }\n" " });\n" "})(jQuery);\n" "</script>\n" "<script src=\"/js/miwifi-monitor.js\"></script>\n" "<script>\n" "// 流量统计\n" "(function(){\n" " var IS_MOBILE = (\n" " navigator.userAgent.match(/Android/i)\n" " || navigator.userAgent.match(/webOS/i)\n" " || navigator.userAgent.match(/iPhone/i)\n" " || navigator.userAgent.match(/iPad/i)\n" " || navigator.userAgent.match(/iPod/i)\n" " || navigator.userAgent.match(/BlackBerry/i)\n" " || navigator.userAgent.match(/Windows Phone/i)\n" " );\n" " var PAGEURL = document.URL.split('/web/')[1];\n" " var PAGE_MONITOR_CONF = {\n" " deviceId: 'f051907f-3c7c-8667-a254-327d09463e2c',\n" " isMobile: IS_MOBILE ? IS_MOBILE[0] : 'pc',\n" " url: PAGEURL ? '/web/' + PAGEURL : '/web/login',\n" " romVersion: '2.11.48',\n" " romChannel: 'stable',\n" " hardwareVersion: 'R3'\n" " };\n" " MIWIFI_MONITOR.setProject('MIWIFIWEB');\n" " MIWIFI_MONITOR.log(PAGE_MONITOR_CONF, 'track');\n\n" " $(document).ajaxSend(function(event, jqxhr, settings) {\n" " var apiUrl = settings.url.split('/api/')[1],\n" " api = '/api/' + apiUrl.split('?')[0],\n" " apiParams = StringH.queryUrl(apiUrl);\n\n" " // console.log(apiUrl, api, apiParams);\n\n" " var API_MONITOR_CONF = ObjectH.mix({element: 'apicall', api: api}, [PAGE_MONITOR_CONF, apiParams]);\n" " // console.log(API_MONITOR_CONF);\n" " MIWIFI_MONITOR.log(API_MONITOR_CONF);\n" " });\n" "}());\n" "</script>\n" "<script>\n" "$(function(){\n" " var pwdErrorCount = 0;\n" " $( '#password' ).focus();\n\n" " $( '#password' ).on( 'keypress', function( e ) {\n" " $('#rtloginform .form-item' ).removeClass( 'form-item-err' );\n" " $('#rtloginform .form-item .t' ).hide();\n" " });\n\n" " function buildUrl( s, token ){\n" " if (!window.location.origin){\n" " window.location.origin = window.location.protocol+\"//\"+window.location.host;\n" " }\n" " return window.location.origin + '/cgi-bin/luci/;stok=' + token+ '/web/setting/' + s;\n" " }\n\n" " function loginHandle ( e ) {\n" " e.preventDefault();\n" " var formObj = document.rtloginform;\n" " var pwd = $( '#password' ).val();\n" " if ( pwd == '') {\n" " return;\n" " }\n" " var nonce = Encrypt.init();\n" " var oldPwd = Encrypt.oldPwd( pwd );\n" " var param = {\n" " username: 'admin',\n" " password: oldPwd,\n" " logtype: 2,\n" " nonce: nonce\n" " };\n" " $.pub('loading:start');\n" " var url = '/cgi-bin/luci/api/xqsystem/login';\n" " $.post( url, param, function( rsp ) {\n" " $.pub('loading:stop');\n" " var rsp = $.parseJSON( rsp );\n" " if ( rsp.code == 0 ) {\n" " var redirect,\n" " token = rsp.token;\n" " if ( /action=wan/.test(location.href) ) {\n" " redirect = buildUrl('wan', token);\n" " } else if ( /action=lannetset/.test(location.href) ) {\n" " redirect = buildUrl('lannetset', token);\n" " } else {\n" " redirect = rsp.url;\n" " }\n" " window.location.href = redirect;\n" " } else if ( rsp.code == 403 ) {\n" " window.location.reload();\n" " } else {\n" " pwdErrorCount ++;\n" " var errMsg = '密码错误';\n" " if (pwdErrorCount >= 4) {\n" " errMsg = '多次密码错误,将禁止继续尝试';\n" " }\n" " Valid.fail( document.getElementById('password'), errMsg, false);\n" " $( formObj )\n" " .addClass( 'shake animated' )\n" " .one( 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){\n" " $('#password').focus();\n" " $( this ).removeClass('shake animated');\n" " } );\n" " }\n" " });\n" " }\n" " $( '#rtloginform' ).on( 'submit', loginHandle);\n" " $( '#btnRtSubmit' ).on( 'click', loginHandle);\n" " $.placeholder();\n" "});\n" "</script>\n") match = regex.search(test_str) if match: print(f"Match was found at {match.start()}-{match.end()}: {match.group()}") for group_num, group in enumerate(match.groups(), start=1): print(f"Group {group_num} found at {match.start(group_num)}-{match.end(group_num)}: {group}")

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Python, please visit: https://docs.python.org/3/library/re.html