JS学习笔记——正则表达式面试题(永不停更)

我把面试题大致分为:字符匹配字符分割字符截取字符转换

1、字符匹配

1、匹配:匹配以尖括号括起来的以a开头的字符串

var str = "this is a <a herf='www.baidu.com'>,not a <img src='xxx'>";
var reg = /<a[^>]+>/g;

console.log(str.match(reg));
//["<a herf='www.baidu.com'>"]

在这里插入图片描述

2、匹配:xxyy模式

var reg = /(\w)\1(\w)\2/g;

在这里插入图片描述

3、匹配:判断是否符合电话号码格式

function isPhone(tel) {
    var regx = /^1[34578]\d{9}$/;
    return regx.test(tel);
}

在这里插入图片描述

4、匹配:判断是否符合美元$格式

题目:给定字符串 str,检查其是否符合美元$书写格式

1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用,分隔
3、如果有小数部分,则小数部分长度为 2

正确的格式如:$1,023,032.03 或者 $2.03

错误的格式如:$3,432,12.12 或者 $34,344.3

function isUSD(str) {
    var regx = /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/;
    return regx.test(str);
}

在这里插入图片描述

5、匹配:判断是否符合邮箱格式

题目:写出正则匹配邮箱格式。
因为邮箱的格式每个地方都不一样,但是大致原理都相似,所以这里只写基本的路径匹配

function isEmail(email) {
    var regx =  /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
    return regx.test(email);
}
isEmail("12345678@qq.com") //true

在这里插入图片描述

function isEmail(email) {
    var regx =   /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/
    return regx.test(email);
}
isEmail("12345发货678@qq.com")//false

在这里插入图片描述

6、匹配:判断是否符合身份证格式

题目:身份证号码可能为15位或18位,15位为全数字,18位中前17位为数字,最后一位为数字或者X,写出正则匹配出身份证格式

function isCardNo(number) {
    var regx = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return regx.test(number);
}

isCardNo('123456789012345678') //true

在这里插入图片描述

7、匹配:匹配密码合法性

题目:密码长度是6-12位,由数字、小写字母和大写字母组成,但必须至少包括2种字符

let reg = /(((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z]))^[a-zA-Z\d]{6,12}$/

console.log(reg.test('123456')) // false
console.log(reg.test('aaaaaa')) // false
console.log(reg.test('AAAAAAA')) // false
console.log(reg.test('1a1a1a')) // true
console.log(reg.test('1A1A1A')) // true
console.log(reg.test('aAaAaA')) // true
console.log(reg.test('1aA1aA1aA')) // true

分析过程:

题目由三个条件组成:

  • 密码长度是6-12位
  • 由数字、小写字符和大写字母组成
  • 必须至少包括2种字符

第一步:满足条件1、2

cosnt  reg = /^[a-zA-Z\d]{6,12}$/

第二步:必须包含某种字符(数字、大写字母、小写字母)

let reg = /(?=.*\d)/
// 这个正则的意思是,匹配的是一个位置
// 这个位置需要满足`任意数量的符号,紧跟着是个数字`,
// 注意它最终得到的是个位置而不是其他的东西
// (?=.*\d)经常用来做条件限制

console.log(reg.test('hello')) // false
console.log(reg.test('hello1')) // true
console.log(reg.test('hel2lo')) // true

第三步:必须包含2种及以上字符

有下面四种排列组合方式:

  • 数字和小写字母组合
  • 数字和大写字母组合
  • 小写字母与大写字母组合
  • 数字、小写字母、大写字母一起组合(但其实前面三种已经覆盖了第四种了)
// 表示条件1和2
let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))/

// 表示条件条件3
let reg = /(?=.*[a-z])(?=.*[A-Z])/

// 表示条件123
let reg = /((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z])/

// 表示题目所有条件
let reg = /(((?=.*\d)((?=.*[a-z])|(?=.*[A-Z])))|(?=.*[a-z])(?=.*[A-Z]))^[a-zA-Z\d]{6,12}$/


console.log(reg.test('123456')) // false
console.log(reg.test('aaaaaa')) // false
console.log(reg.test('AAAAAAA')) // false
console.log(reg.test('1a1a1a')) // true
console.log(reg.test('1A1A1A')) // true
console.log(reg.test('aAaAaA')) // true
console.log(reg.test('1aA1aA1aA')) // true

2、字符分割

1、分割:数字价格千分位分割

题目:将123456789变成123,456,789

var str = '123456789000'
var reg = /(?!^)(?=(\d{3})+$)/g
str.replace(reg,'.') 

在这里插入图片描述

var str = '123456789000'
var reg = /(?=(\B)(\d{3})+$)/g
str.replace(reg,'.')

在这里插入图片描述

2、分割:手机号按照 3-4-4 位分割

题目:将手机号18379836654转化为183-7983-6654

整体思路和前面千分位分割类似,

let mobile = '18379836654' 
let reg = /(?=(\d{4})+$)/g 

console.log(mobile.replace(reg, '-'))

在这里插入图片描述

3、分割(扩展):手机号按照 3-4-4 分割

题目:

我们希望在输入手机号码的过程中,边输入边分割,这就需要不断格式化。

123 => 123
1234 => 123-4
12345 => 123-45
123456 => 123-456
1234567 => 123-4567
12345678 => 123-4567-8
123456789 => 123-4567-89
12345678911 => 123-4567-8911

正则结果:

const abc = (mobile) => {
  return String(mobile).slice(0,11)
      .replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
      .replace(/(?<=[\d-]{8})\d{1,4}/, ($0) => '-' + $0)
}

console.log(abc(13812345678))

分析:

在前面数字金额按照千分位分割的时候,我们使用了(?=p),即 零宽正向先行断言,该断言的作用如下:

  • exp1(?=exp2):表示查找 exp2 前面的 exp1

当时是要保证要寻找的位置后面应该满足某些要求

关于零宽断言,可以参考这篇文章

现在匹配手机号则是按照从前到后的输入顺序,所以这里用(?=p)就不太合适了,例如1234就会变成-1234。我们需要另寻他法, 即可以使用(?<=p),零宽正向后行断言,该断言的作用如下:

  • (?<=exp2)exp1:表示查找 exp2 后面的 exp1

所以,第一步,把第一个-匹配出来

const abc = (mobile) => {
  return String(mobile).replace(/(?<=\d{3})\d+/, ($0)=>'-'+$0)      
}

console.log(abc(123))       // 123
console.log(abc(1234))      // 123-4
console.log(abc(123456789)) // 123-456789

第二步,把第二个-匹配出来

const abc = (mobile) => {
  return String(mobile).slice(0,11)
      .replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
      .replace(/(?<=[\d-]{8})\d{1,4}/, ($0) => '-' + $0)
}

console.log(abc(123)) // 123
console.log(abc(1234)) // 123-4
console.log(abc(12345)) // 123-45
console.log(abc(123456)) // 123-456
console.log(abc(1234567)) // 123-4567
console.log(abc(12345678)) // 123-4567-8
console.log(abc(123456789)) // 123-4567-89
console.log(abc(12345678911)) // 123-4567-8911

3、字符截取

1、截取:获取 url 中?后的query参数

题目:

  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组
function getUrlParam(url, key) {
   var arr = {};
   url.replace(/\??(\w+)=(\w+)&?/g, function(match, matchKey, matchValue) {
      if (!arr[matchKey]) {
          arr[matchKey] = matchValue;
      } else {
          var temp = arr[matchKey];
          arr[matchKey] = [].concat(temp, matchValue);
      }
   });
   if (!key) {
       return arr;
   } else {
       for (ele in arr) {
           if (ele = key) {
               return arr[ele];
           }
       }
       return '';
   }
}

getUrlParam('https://www.xxxxx.com/?car=binli&adc=uzi&name=zhanwei&age=41&name=chen&age=24&cityId=100&app=wps')

在这里插入图片描述

2、截取:去除字符串首尾的空格符号(即trim函数)

题目:去除字符串首部和尾部的空格符

正则结果:

// 去除空格法
const trim = (str) => {
  return str.replace(/^\s*|\s*$/g, '')    
}

trim('  老Chen先生 123 哈哈哈  ') //'老Chen先生 123 哈哈哈'

在这里插入图片描述

3、截取:将一串数字中连续且重复的数字提取出来

题目:将有重复的字符提取出来,例如:123237987981028686,提取 [‘23’, ‘798’, ‘86’]

正则结果:

const abc = (str) => {
  let arr = []
  const reg = /(.+)\1+/g
  str.replace(reg, ($0, $1) => {
    $1 && arr.push($1)
  })
  return arr
}

console.log(abc('123237987981028686')) 
//['23', '798', '86']

其中,三次的$0$1分别是:
在这里插入图片描述
分析:

题目中有几个关键信息:

  1. 连续重复的字符
  2. 长度是不限的(如23、45是两位、6是一位)

那什么是连续重复呢?

11是连续重复、22也是连续重复、111当然也是。也就是说某些字符X之后一定也是跟着X,就叫连续重复。如果很明确知道X是就是1,那么/11+/也就可以匹配了,但关键是这里的X是不明确的,怎么办呢?

使用反向引用的正则知识可以很方便解决这个问题。

第一步:写出表示有一个重复字符的正则

// 这里的X可用.来表示,即所有的字符,并用括号进行引用,紧跟着反向应用\1,也就是体现了连续重复的意思啦
let repeatRe = /(.)\1/

console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('123')) // false

第二步:写出表示有n个重复字符的正则

注意:因为并不确定是要匹配11还是45 ,45所以括号内需要用量词+来体现n个重复字符,而反向引用本身也可以是大于一个的,例如 45 45 45

let repeatRe = /(.+)\1+/

console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('454545')) // true
console.log(repeatRe.test('124')) // false

第三步:提取连续重复的字符

const abc = (str) => {
  let arr = []
  const reg = /(.+)\1+/g
  str.replace(reg, ($0, $1) => {
    $1 && arr.push($1)
  })
  return arr
}

console.log(abc('123237987981028686')) 
//['23', '798', '86']

4、字符转换

1、转换:将字符串 - 转为 驼峰

题目:the-first-name 变成 theFirstName

var str = "the-first-name"
var reg = /-(\w)/g
str.replace(reg,($,$1)=>{
    return $1.toUpperCase()
})

在这里插入图片描述

var str = "get-element-by-id"
var reg = /-\w/g
str.replace(reg,($)=>{
  return $.slice(1).toUpperCase()
})

在这里插入图片描述

2、转换:字符串aaabbbbcccc变成abc

var str = 'aaaaaaaaabbbbbbbbcccccc'
var reg = /(\w)\1*/g

console.log(str.replace(reg,'$1'))

在这里插入图片描述

3、转换:将数字替换成汉字

var str = '20171001';
var arr = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"];
str = str.replace(/\d/g,function () {
 	var num = arguments[0]; // 把捕获的内容,作为数组的下标
 	return arr[num];
});

console.log(str); //贰零壹柒壹零零壹

4、转换:HTML转义

前提:防止XSS攻击的方式之一就是做HTML转义,转义规则如下,要求将对应字符转换成等值的实体。而反转义则是将转义后的实体转换为对应的字符
在这里插入图片描述
正则结果:

var reg = /[&<>"']/g
var obj = {
    '&': 'amp',
    '<': 'lt',
    '>': 'gt',
    '"': 'quot',
    "'": '#39'
 }
var str = '<div>哈哈123<p>里面字符</p></div>'
str.replace(reg, ($0) =>{
    console.log('$0',$0)
    return `&${obj[$0]}`

})

$0 <
$0 >
$0 "
$0 "
$0 <
$0 >
'&ltdiv&gt大家好,我是&quot帅哥&quot&lt/div&gt'

(注意:类似这种某个字符可能是多种情况之一的时候,我们一般会使用字符组来做 ,动态的改变,即[&<>"']


本博客参考:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python学习笔记|字符串与正则表达式练习题答案 1. 练习题1: 题目:给定一个字符串s,找出其中的连续的最长的数字串。 答案:可以通过正则表达式来匹配数字串,然后使用max函数找出最长的。 代码示例: import re def find_longest_num_str(s): num_str_list = re.findall('\d+', s) longest_str = max(num_str_list, key=len) return longest_str s = "ab1234c56789def" print(find_longest_num_str(s)) 输出:56789 2. 练习题2: 题目:给定一个字符串s,将其中的每个空格替换为"%20"。 答案:可以通过正则表达式的sub函数来实现替换。 代码示例: import re def replace_space(s): new_s = re.sub(' ', '%20', s) return new_s s = "Hello World" print(replace_space(s)) 输出:Hello%20World 3. 练习题3: 题目:给定一个字符串s,判断它是否为回文字符串。 答案:可以使用切片操作将字符串反转,然后与原字符串进行比较。 代码示例: def is_palindrome(s): return s == s[::-1] s = "abcba" print(is_palindrome(s)) 输出:True ### 回答2: 以下是关于字符串和正则表达式练习题的答案: 1. 给定一个字符串s,编写一个函数,返回该字符串的反转字符串。 def reverse_string(s): return s[::-1] 2. 给定一个字符串s,编写一个函数,返回是否是回文字符串。 def is_palindrome(s): return s == s[::-1] 3. 给定一个字符串s和一个字符c,编写一个函数,返回字符串s中字符c的出现次数。 def count_char(s, c): return s.count(c) 4. 给定一个字符串s,编写一个函数,返回字符串s中的所有单词列表。 def split_words(s): return s.split() 5. 给定一个字符串s,编写一个函数,返回字符串s中的所有数字列表。 import re def extract_numbers(s): return re.findall(r'\d+', s) 这只是一些可能的答案,其中的解决方法可以有很多种。每个问题都有不同的解决方案,具体取决于个人的编程风格和需求。希望这些答案能够帮助你理解和学习Python中的字符串和正则表达式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值