这篇文章上次修改于 196 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

正则是一个应用很广泛的方法,在学校的课程中和刷题过程中都遇到过有关正则表达式的问题,但是一直都没有认真的学习,一般就是用的时候看一眼用完就跑了,今天看到了手写获取url参数的题,借这个机会系统的学习的正则

问题

给你一个get请求的url链接,获取到其中指定的参数

格式:"https://www.baidu.com/t.html?name=mick&age=20"

URL参数是追加到 URL 上的一个名称/值对。参数以问号 (?) 开始并采用 name=value 的格式。如果存在多个 URL 参数,则参数之间用一个 (&) 符隔开。

看到这个题我想到的第一想法就是正则,但是让我们学习一下其他的几种写法

现代方式

直接利用浏览器提供的API,最简单的方式

function getQueryString(name) {
  const url_string = "https://www.baidu.com/t.html?name=mick&age=20"; // window.location.href
  const url = new URL(url_string);
  return url.searchParams.get(name);
}

console.log(getQueryString('name')) // mick
console.log(getQueryString('age')) // 20

利用URL()将字符串转化为URL,然后使用searchParams.get()函数将其中需要的参数提取

老式字符串循环法

核心私信是通过String.split()函数将url不断分割成块,最后获取到自己需要的部分,值得注意的是,url可能是经过编码之后才进行传输的,Url编码的原则就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。经过编码之后,可以防止歧义(如变量中带有特殊字符导致解析的错误)并允许特殊语言符合(中文)转化为ascii码后传输。所以在处理url之前首先要使用decodeURIComponent进行解码

function getQueryString(name) {
  var url_string = "https%3A%2F%2Fwww.baidu.com%2Ft.html%3Fname%3Dmick%26age%3D20"; // window.location.href
  url_string=decodeURIComponent(url_string)
  var params = url_string.split('?')[1]; // 获取?号后面的参数 name=mick&age=20
  if (!params) return null; // 如果无参,返回null
  var vars = params.split("&"); // 将参数分割成数组 ['name=mick', 'age=20']
  var query_string = {};
  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("="); // 将参数的key和值进行分割成 ['name', 'mick']
    var key = pair[0]; // 参数key
    var value = pair[1]; // 参数值
    if (name === key) { // 如果匹配到对应key返回
      return value;
    }
  }
  return null;
}

console.log(getQueryString('name')) // mick
console.log(getQueryString('age')) // 20

正则式表达法

regular expression(regex,re),使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。

在js中,有专门用于进行正则表达的对象RegExp

var patt=new RegExp(pattern,modifiers);

或者更简单的方式:

var patt=/pattern/modifiers;

pattern是具体的匹配模式,而modifiers为修饰符

i执行对大小写不敏感的匹配。
g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m执行多行匹配。

方括号用于查找某个范围内的字符:

[abc]查找方括号之间的任何字符。
[1(https://www.runoob.com/jsref/jsref-regexp-charset-not.html)查找任何不在方括号之间的字符。
[0-9]查找任何从 0 至 9 的数字。
[a-z]查找任何从小写 a 到小写 z 的字符。
[A-Z]查找任何从大写 A 到大写 Z 的字符。
[A-z]查找任何从大写 A 到小写 z 的字符。
[adgk]查找给定集合内的任何字符。
2查找给定集合外的任何字符。
(red\blue\green)查找任何指定的选项。

元字符(Metacharacter)是拥有特殊含义的字符:

元字符描述
.查找单个字符,除了换行和行结束符。
w查找数字、字母及下划线。
W查找非单词字符。
d查找数字。
D查找非数字字符。
s查找空白字符。
S查找非空白字符。
b匹配单词边界。
B匹配非单词边界。
0查找 NULL 字符。
n查找换行符。
f查找换页符。
r查找回车符。
t查找制表符。
v查找垂直制表符。
xxx查找以八进制数 xxx 规定的字符。
xdd查找以十六进制数 dd 规定的字符。
uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。
量词描述
n+匹配任何包含至少一个 n 的字符串。例如,/a+/ 匹配 "candy" 中的 "a","caaaaaaandy" 中所有的 "a"。
n*匹配任何包含零个或多个 n 的字符串。例如,/bo*/ 匹配 "A ghost booooed" 中的 "boooo","A bird warbled" 中的 "b",但是不匹配 "A goat grunted"。
n?匹配任何包含零个或一个 n 的字符串。例如,/e?le?/ 匹配 "angel" 中的 "el","angle" 中的 "le"。
n{X}匹配包含 X 个 n 的序列的字符串。例如,/a{2}/ 不匹配 "candy," 中的 "a",但是匹配 "caandy," 中的两个 "a",且匹配 "caaandy." 中的前两个 "a"。
n{X,}X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。例如,/a{2,}/ 不匹配 "candy" 中的 "a",但是匹配 "caandy" 和 "caaaaaaandy." 中所有的 "a"。
n{X,Y}X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。例如,/a{1,3}/ 不匹配 "cndy",匹配 "candy," 中的 "a","caandy," 中的两个 "a",匹配 "caaaaaaandy" 中的前面三个 "a"。注意,当匹配 "caaaaaaandy" 时,即使原始字符串拥有更多的 "a",匹配项也是 "aaa"。
n$匹配任何结尾为 n 的字符串。
3(https://www.runoob.com/jsref/jsref-regexp-ncaret.html)匹配任何开头为 n 的字符串。
?=n匹配任何其后紧接指定字符串 n 的字符串。
?!n匹配任何其后没有紧接指定字符串 n 的字符串。

RegExp 对象方法

方法描述
compile在 1.5 版本中已废弃。 编译正则表达式。
exec检索字符串中指定的值。返回找到的值,并确定其位置。
test检索字符串中指定的值。返回 true 或 false。
toString返回正则表达式的字符串。

支持正则表达式的 String 对象的方法

方法描述FFIE
search检索与正则表达式相匹配的值。14
match找到一个或多个正则表达式的匹配。14
replace替换与正则表达式匹配的子串。14
split把字符串分割为字符串数组。14

正则表达式解法

function getQueryString(name) {
    var query_string = "?name=mick&age=20"; // window.location.search
  if (!query_string) return null; // 如果无参,返回null
  var re = /[?&]?([^=]+)=([^&]*)/g;
  var tokens;
  while (tokens = re.exec(query_string)) {
    if (decodeURIComponent(tokens[1]) === name) {
      return decodeURIComponent(tokens[2]);
    }
  }
  return null;
}

console.log(getQueryString('name')) // mick
console.log(getQueryString('age')) // 20

正则表达式的用法还有一道题是lc上的表示数组的字符串,当时做的时候十分痛苦就直接看答案了,今天正好补充一下

题目地址:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/

题目描述

数值(按顺序)可以分成以下几个部分:

若干空格
一个 小数 或者 整数
(可选)一个 'e' 或 'E' ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:

(可选)一个符号字符('+' 或 '-')
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
一个点 '.' ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:

(可选)一个符号字符('+' 或 '-')
至少一位数字

var isNumber = function (s) {
    return /^([+-]?((\d*\.\d+)|\d+|(\d+\.\d*)))([eE][+-]?\d+)?$/.test(s.trim())
    //行的开始,符号, 浮点数|整数|浮点数    e   符号  整数 匹配行尾  去掉前后空格
};

  1. abc]
  2. adgk
  3. n