正则表达式,你不会用太可惜

文章目录

    • 说明
    • 创建正则表达式的三种方式
      • 方式一
      • 方式二
      • 方式三
    • 正则表达式修饰符
      • i (IgnoreCase)
      • g (global)
      • m (multiple lines)
    • 正则表达式
      • [ ]
      • ()
    • 元字符
      • .
      • w 是word的缩写
      • d 是digit的缩写
      • s 是 space的缩写
      • 其它间隙元字符
    • 不占位修饰符
      • b是border的缩写
      • ^
      • $
      • `?=`和`?!`
    • 量词
    • 正则的反向引用 `(n)\数字`
    • RegExp 对象方法
      • `exec()` 是 execute的缩写
      • `test()`
    • 支持正则表达式的 String 对象的方法
      • `search()`
      • `match()`
      • `split()`
      • `replace()`

在这里插入图片描述

说明

后面的介绍中,我会说某些规则占位或者不占位,占位就是指匹配的结果中,有字符和这符号所表示的规则有直接联系,不占位就是所匹配的结果中没有字符和这符合有直接联系。

^在开头属于不占位符,开始符

var reg1 = /^ab/
const result = 'abABCDab'.match(reg)
console.log(result) //  ['ab'] 匹配的结果ab和^没有直接联系,规则/^ab/中,a和b是两位,所以匹配的一个字符串也只有两位

创建正则表达式的三种方式

方式一

var reg1 = /ab/

方式二

var reg2 = new RegExp(reg1)

方式三

var reg3 = RegExp(reg1)

有什么区别呢

var reg1 = /ab/
var reg2 = new RegExp(reg1)
var reg3 = RegExp(reg1)
console.log(reg1 === reg3) // true
console.log(reg1 === reg2) // false

如上代码所述,reg1和reg3本质上是同一个正则对象,相当于将reg1赋值给了reg3,但reg2不同,它深度拷贝了reg1。

再验证一下

var reg1 = /ab/
var reg2 = new RegExp(reg1)
var reg3 = RegExp(reg1)
reg1.name = 'dx'
console.log(reg2.name) // undefined
console.log(reg3.name) // dx

正则表达式修饰符

修饰符一共就只有三个 g/i/m,它们通常出现在正则表达式的最后面,可以自由组合,顺序无所谓,但每个修饰符只能出现一次。
/ab/g /ab/ig /ab/gm /ab/igm /ab/gim

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

i (IgnoreCase)

忽略字母大小写

  const reg = new RegExp(/ab/i)
  const result = 'djwiAB'.match(reg)
  console.log(result)
  const result2 = 'fsadfaB'.match(reg)
  const boolean1 = reg.test('fsadfaB')
  console.log(result2)
  console.log(boolean1)

result的结果 ['AB', index: 4, input: 'djwiAB', groups: undefined] 这是一个类数组,第0位匹配到AB
result2的结果 ['aB', index: 5, input: 'fsadfaB', groups: undefined] 类数组第0位匹配aB
boolean1的结果是true
以上三个结果都表明,i作为忽略大小写的修饰符,挺好使,而且也经常用。

g (global)

全局匹配修饰符

  const reg = new RegExp(/ab/g)
  const result = 'abABCDab'.match(reg)
  console.log(result) //  ['ab', 'ab']
  const result2 = 'abaabb'.match(/ab/)
  console.log(result2) //  ['ab', index: 0, input: 'abaabb', groups: undefined]

result 匹配到了两次,而result2只匹配到了一次。g的作用就是找到整个字符串中所有符合条件的字符。如果没有g就只会匹配到第一个。

  const reg = new RegExp(/ab/ig)
  const result = 'abABCDab'.match(reg)
  console.log(result) // ['ab', 'AB', 'ab']

g结合i再匹配了一下,忽略了大小写,AB也被匹配进去了。

m (multiple lines)

支持多行匹配,看个例子,简单说明一下m的用法,很少用到。
\n表示换行,^ab表示匹配字符串中以ab开头的那一部分。

  const reg = new RegExp(/^ab/) 
  const result = 'ABCD\nab'.match(reg)
  console.log(result) // null

如果加一个m,可以看到结果result中 有一个index为5的属性,证明\n后的ab被匹配到了

  const reg = new RegExp(/^ab/m) 
  const result = 'ABCD\nab'.match(reg)
  console.log(result) // ['ab', index: 5, input: 'ABCD\nab', groups: undefined]

m的作用就是每遇到一次\n就认为后面的内容是全新的一行,当然也就符合以ab开头的匹配规则。

  const reg = new RegExp(/^ab/gim) 
  const result = 'ABCD\nab'.match(reg)
  console.log(result) // ['AB', 'ab']

正则表达式

[ ]

每一个[ ]表示一位,而里面的内容,就是这一位的取值范围
[abc] 从abc中取一个出来,a或者b或者c都符合这个位置的要求
[0a] 0或者a都符合这个位置的要求

  const reg = new RegExp(/[ab]/g) 
  const result = 'ABCDab'.match(reg)
  console.log(result) // ['a', 'b']

result匹配到了两个,是因为g修饰符,一个a和一个b,是因为匹配规则是匹配一位,一个[]表示一位,这一位可以是a,也可以是b

[]里面可以加^,和之前的^不同,方括号里的^表示凡是不在方括号表示范围的字符都可以。

  const reg = new RegExp(/[^ab]/g) // 查找字符串中不是a或者不是b的一位字符 
  const result = 'ABCDab'.match(reg)
  console.log(result) //['A', 'B', 'C', 'D']

[]里面可以加-,表示一定的范围,如果你想让某一位是数字,难道要[0123456789],可以使用[0-9]
-在其它地方使用都没有特殊意义,只是占一位的字符-
[0-9] 表示这一位是数字0到9都可以
[a-z] 表示这一位是字母a到z都可以
[A-Z]表示这一位是字母A到Z都可以
[A-z]表示这一位是字母A到z都可以,这就囊括了所有的字母,但A必须在前面,因为大写字母的ascll码更小,不能[z-A],会报错。

  const reg = new RegExp(/[^0-9]/g)  // 匹配出所有非数字,
  const result = '123AB'.match(reg)
  console.log(result) // ['A', 'B']
  const reg = new RegExp(/[^0-9A-z]/g)  // 匹配出所有非数字非字母
  const result = '123AB*-'.match(reg)
  console.log(result) // ['*', '-']

()

()可以加 || 表示或

  const reg = new RegExp(/(a|b)/g) 
  const result = 'ABCDab'.match(reg)
  console.log(result) // ['a', 'b']

(a|b)表示|左边的a或者右边的b都符合匹配要求,好像和[ab]没啥区别,

  const reg = new RegExp(/(abc|bcd)/ig) 
  const result = 'ABCDabcd'.match(reg)
  console.log(result) //['ABC', 'abc']

(abc|bcd) 表示连着的abc或者连着的bcd都可以

()里面的是左右二选一组,一组可能有多位,而[]里面是范围内选一位。

元字符

.

在正则表达式中某些字母或字母组合具有特殊意义,只列出重要的

元字符特殊意义
.查找单个字符,除了换行符\n或行终止符\r
  const reg = new RegExp(/./g) 
  const result = 'AB1\n-\r0'.match(reg)
  console.log(result) // ['A', 'B', '1', '-', '0']

w 是word的缩写

元字符特殊意义
\w查找数字或字母,默认一位。和[A-z0-9] 表示意义相同
\W\w相反,查找非数字非字母的字符,默认一位 和[^A-z0-9] 表示意义相同
  const reg = new RegExp(/\w\w/g) // 匹配所有连续两位是字母或数字的片段 
  const result = 'AB1\n-\r ba11'.match(reg)
  console.log(result) // ['AB', 'ba', 11]
  const reg = new RegExp(/\W\W/g) // 匹配所有连续两位是非字母并且非数字的片段 
  const result = 'AB1\n-\r ba11'.match(reg)
  console.log(result) // ['\n-', '\r ']

d 是digit的缩写

元字符特殊意义
\d查找任意数字,默认一位。和[0-9] 表示意义相同
\D\d相反,查找非数字 和[^0-9] 表示意义相同
  const reg = new RegExp(/\d\d/g) // 匹配所有连续两位是数字的片段 
  const result = 'AB177b12a'.match(reg)
  console.log(result) // ['17', '12']
  const reg = new RegExp(/\d\D/g) // 匹配所有连续两位,一位数字连接一位非数字,并且数字在前的片段 
  const result = 'AB177b12a'.match(reg)
  console.log(result) // ['7b', '2a']

s 是 space的缩写

元字符特殊意义
\s查找空格或\n\r\t\v\f,默认一位。
\S\s相反,默认一位
 const reg = new RegExp(/\s/g) 
 const result = 'AB1\n-\r\t\v\f 0  '.match(reg)
 console.log(result) // ['\n', '\r', '\t', '\v', '\f', ' ', ' ', ' ']
 const reg = new RegExp(/\S\s/g) 
 const result = 'AB1\n-\r\t\v\f 0  '.match(reg)
 console.log(result) // ['1\n', '-\r', '0 ']

其它间隙元字符

元字符特殊意义
\n查找换行符 占位
\f查找换页符 占位
\r查找回车符 占位
\t查找制表符 占位
\v查找垂直制表符 占位

不占位修饰符

一般都是都附近的规则有位置上的修饰,比如要求n必须在开头,或必须在结尾,或必须诶着什么,或者不能诶着什么

b是border的缩写

不占位修饰符特殊意义
\b边界字符,一段连续字符 开始的那一位 或者 一段连续字符 结束的那一位 不占位
\B非边界字符,不占位

看例子更容易理解

 const reg = new RegExp(/\b\w/g) // 查找与间隙相连,并且间隙在前的字母或数字 一位,因为\b不占位
 const result = 'dengxi is 123'.match(reg)
 console.log(result) // [d, i, 1]
 const reg = new RegExp(/\w\b/g) // 查找与间隙相连,并且字母或数字在前 一位,因为\b不占位
 const result = 'dengxi is 123'.match(reg)
 console.log(result) // [i, s, 3]

字符串开头,空格,\n,\r,\t,\f,\v 字符串结尾,这些都算间隙

 const reg = new RegExp(/\w\b/g) // 查找与间隙相连,并且字母或数字在前的 一位 字符,因为\b不占位
 const result = 'dengxi\nyang\rxi'.match(reg)
 console.log(result) // ['i', 'g', 'i']
 const reg = new RegExp(/\w\B/g) // 所有后面不跟着间隙的数字或者字母 一位,因为\B不占位
 const result = 'dengxi\nyang\rxi'.match(reg)
 console.log(result) // ['d', 'e', 'n', 'g', 'x','y','a','n','x']

^

在开头放置表示行开头,在[]中放置表示中括号的范围取反。

不占位修饰符特殊意义
^n找到字符串中以n作为开头的那一部分,n可以是一位或者多位,^本身不占位
[^n] 找到非n提供范围内的一位字符, ^本身不占位

\n是换行,\r回车,都会出现新的一行

另外修饰符m是能够换行匹配的关键

 const reg = new RegExp(/^\w\w/gm) 
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['12', '11', 'bb', '02']
 const reg = new RegExp(/^\w\w/g) 
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['12']

$

在末尾放置放置,表示在行末尾

不占位修饰符特殊意义
n$找到字符串中以n作为结尾的那一部分,n可以是一位或者多位,$本身不占位

\n是换行,\r回车,都会出现新的一行
另外修饰符m是能够换行匹配的关键

 const reg = new RegExp(/\w\w$/gm) 
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['B1', '11', '01', '02']
 const reg = new RegExp(/\w\w$/g) 
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['02']

?=?!

不占位修饰符特殊意义
(?=n)匹配任何其后紧接指定字符串 n 的字符串。
(?!n)匹配任何其后没有紧接指定字符串 n 的字符串。

?=n要配合小括号使用,否则不生效

 const reg = new RegExp(/\w(?=1)/g) // 匹配后面跟着1的数字或字母,(?=1)不占位,所以匹配出来的结果只有1位
 const result = '12AB21\n21\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) //['2', '2', '0']
 const reg = new RegExp(/\w\w(?!\w)/g) // 匹配后面没有数字或字母跟着的 连续两位数字或字母,(?!\w)不占位,所以匹配出来的结果只有2位
 const result = '12AB21\n21\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['21', '21', 'bb', 'cc', 'dd', '01', '02']

量词

量词本身是不占位的,但是,量词会将临近它的 有符占位数的规则 做一个乘法,比如 /\w{2}/的意义就相当于/\w\w/,就是将\w给乘以2。

量词特殊意义
n{X}匹配包含 X 个 n 的序列的字符串。
n{X,Y}匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,}匹配包含至少 X 个 n 的序列的字符串。

X和Y都是数字,前面的小,后面的大,n表示任意拥有占位数的正则规则。

 const reg = new RegExp(/\w{2}/g) // 匹配两位,连续的是字母或数字的字符串
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['12', 'AB', '11', 'bb', 'cc', 'dd', '01', '02']

正则表达式的贪婪原则,能匹配长的,就不匹配短的,下面的规则中,是两位或者三位都可以,但优先查看是否三位满足正则的要求。

 const reg = new RegExp(/\w{2,3}/g) // 匹配两位或者三位,优先匹配三位,连续每个字符都是数字或者字母的字符串
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n02'.match(reg)
 console.log(result) // ['12A', 'B1', '11', 'bb', 'cc', 'dd', '01', '02']

至少两位,尽可能多位

 const reg = new RegExp(/\w{2,}/g) // 匹配 至少连续两位的字符串,尽可能长,要求每一位都是字母或数字
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n0244'.match(reg)
 console.log(result) // ['12AB1', '11', 'bb', 'cc', 'dd', '01', '0244']

下限设置为0

 const reg = new RegExp(/\w{0,4}/g) // 匹配整个字符串,最多4位,至少0位,表示可以为空,0乘以任何东西都是0,所以匹配出了空。
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n0244'.match(reg)
 console.log(result) // ['12AB', '1', '', '11', '', 'bb', '', 'cc', '', 'dd', '', '01', '', '0244', '']

有的人可能会尝试着设置一个上限,而不设置下限,下限连0都不是,其实没什么意义,也没有这个规则

 const reg = new RegExp(/\w{, 4}/g) 
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n0244'.match(reg)
 console.log(result) // null
量词特殊意义
n+匹配任何包含至少一个 n 的字符串。相当于 n{1,}
n*匹配任何包含零个或多个 n 的字符串。相当于 n{0,}
n?匹配任何包含零个或一个 n 的字符串。相当于n{0, 1}

一样有贪婪原则

 const reg = new RegExp(/\w*/g) // 匹配整个字符串,至少0位,表示可以为空,0乘以任何东西都是0,所以匹配出了空。
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n0244'.match(reg)
 console.log(result) ['12AB1', '', '11', '', 'bb', '', 'cc', '', 'dd', '', '01', '', '0244', '']
 const reg = new RegExp(/12?/g) // 匹配整个字符串,至少1位1,2可能乘以0不存在,2可能乘以1为一位,
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n12222222'.match(reg)
 console.log(result) // ['12', '1', '1', '1', '1', '12']
 const reg = new RegExp(/12+/g) // 匹配整个字符串,至少1位1,1位2,2可能乘以1,2可能乘以很多位,贪婪原则
 const result = '12AB1\n11\rbb\tcc\vdd\f01\n12222222'.match(reg)
 console.log(result) // ['12', '12222222']

正则的反向引用 (n)\数字

这个非常有用,很多人都不知道正则还有这种用法,可能学到上面就已经结束了,在 w3c school中,也从来没有提过这种用法。

想要获取字符串中,所有形如aabb的字符串,1122可以,ccdd也可以,只要第一位和第二位相同,第三位和第四位相同即可。

/\w{2}\w{2}/?这肯定不能解决,每一次\w都是独立随机的,这相当于\w\w\w\w确实是四位,但不能保证第一位和第二位相同啊。

所以为了解决形如aabb的问题,就必须得获取第一位的实际内容,然后给第二位,获取第三位的实际内容,给第四位。

/(\w)\1(\w)\2/ 用法(n)\数字,如果是第一次使用,那数字就是1,如果是第二次使用,数字就是2,并且\1本身也是占位的,所以/(\w)\1(\w)\2/这就是四位。

\数字会重复(n)n的实际内容,不是正则规则上的重复,而是匹配出字符串内容的重复。

 const reg = new RegExp(/(\w)\1(\w)\2/g) 
 const result = 'adad ccdd cccc bbpp fhajw'.match(reg)
 console.log(result) // ['ccdd', 'cccc', 'bbpp']

RegExp 对象方法

常用的方法就俩,exec() and test()

exec() 是 execute的缩写

execute就是执行,所以exec只会执行依次匹配,正则表达式后面的g没啥用

 const reg = new RegExp(/(\w)\1(\w)\2/g) 
 const result = reg.exec('adad ccdd cccc bbpp fhajw')
 console.log(result) // ['ccdd', 'c', 'd', index: 5, input: 'adad ccdd cccc bbpp fhajw', groups: undefined]

但是exec会返回一些特殊的东西,其中数组的第一位和第二位很重要,它们对应的就是正则反向引用 匹配到的真实字符。

test()

test()传入需要匹配的字符串,如果字符串符合正则表达式的规则,就返回true,如果字符串不符合,就返回false

 const reg = new RegExp(/(\w)\1(\w)\2/g) 
 const result = reg.test('adad ccdd cccc bbpp fhajw')
 const rsult1 = reg.test('dengxi yangxi')
 console.log(result,rsult1) // true false

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

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

search()

最没用的就是search,返回的是第一个符合正则规则所在字符的位置
正则里面的g没用,只匹配第一个,也只返回第一个,ccdd是能匹配到的第一个,c所在的下标是5,所以结果返回5,如果整个字符串都没找到返回-1

 const reg = new RegExp(/(\w)\1(\w)\2/g) 
 const result = 'adad ccdd cccc bbpp fhajw'.search(reg)
 const result1 = 'dengxi yangxi'.search(reg)
 console.log(result,result1) // 5 -1

match()

用过很多次了,很实用。

split()

将符合正则规则的字符串片段作为分界限,拆分字符串位数组。通常使用split都是传入固定的字符串,作为分界,但有了正则后,只要这些分界有某种规律,它们不必相同,也能直接拆成数组。

 const reg = new RegExp(/\W/g) 
 const result = '12FSAF#FJA*FJD*JDKA/DASF/FASEF'.split(reg)
 const result1 = 'my name is dengxi'.split(reg)
 console.log(result) //['12FSAF', 'FJA', 'FJD', 'JDKA', 'DASF', 'FASEF'] 
 console.log(result1)  //['my', 'name', 'is', 'dengxi']

replace()

真正的王者,最实用的方法,一个字就是香。

我想获取当前的时间,并且以 year-month-day hh:mm:ss的格式返回。

function getTime() {
	const NowDate = new Date()
	const time = NowDate.toString() // 'Thu Nov 16 2023 17:08:25 GMT+0800 (中国标准时间)'
	const month = NowDate.getMonth() // 这里偷懒了,用这种方法获取了月份
	const reg = /.* (\d{2}) (\d{4}) ((\d|:){8}) .*/ // 这个正则能匹配到整个字符串,但将其中关键信息抽取了出来
	const result = time.replace(reg, function($,$1,$2,$3){
		console.log($) // Thu Nov 16 2023 17:27:51 GMT+0800 (中国标准时间)
		console.log($1) // 16
		console.log($2) // 2023
		console.log($3) // 17:15:32
		
		return `${$2}-${month + 1}-${$1} ${$3}`
	})
	
	return result  // '2023-11-16 17:27:51'
}

deng-xi-and-yang-xi 转变为小驼峰命名 dengXiAndYangXi

将诶着-的字符找出来,替换成对应的大写就可以了,一看就跟

function changeStringName(str) {
	const reg = new RegExp (/-(\w)/g)
	const result = str.replace(reg,function($,$1) {
		console.log($)
		console.log($1)
		return $1.toUpperCase()
	})

	return result
}

var a = changeStringName('deng-xi-and-yang-xi')
console.log(a) // dengXiAndYangXi

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/153616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++泛型编程——模板(初识)

C泛型编程——模板(初识) 文章目录 C泛型编程——模板(初识)1. 泛型编程的概念2. 模板2.1 模板格式2.2 函数模板2.3 函数模板的实例化2.3.1 隐式(推演)实例化2.3.2 显式实例化 2.3 类模板3. 模板的本质 本章…

ES7升级、jar包升级、工具类封装,代码改造

一、spring-data-elasticsearch 引入es版本适配 二、jar升级 在项目工程根pom.xml文件中增加maven依赖管理在这里插入图片描述<properties><elasticsearch.spring.version>4.2.0</elasticsearch.spring.version>

Genio 500_MT8385安卓核心板:功能强大且高效

Genio 500(MT8385)安卓核心板是一款功能强大且高效的AIoT平台&#xff0c;内置的AI处理器(APU)工作频率可达500MHz&#xff0c;支持深度学习、神经网络加速和计算机视觉应用。配合高达2500万像素的摄像头&#xff0c;可以为AI相机应用提供清晰、精确的图像&#xff0c;如人脸识…

怎么防止U盘复制电脑文件

随着信息化的快速发展&#xff0c;数据安全问题越来越受到人们的关注。U盘作为一种常用的数据传输工具&#xff0c;有时会被用于非法复制电脑文件&#xff0c;从而给企业或个人带来损失。因此&#xff0c;防止U盘复制电脑文件成为保护数据安全的重要措施之一。 一、我们应该提高…

为什么原生IP可以降低Google play账号关联风险?企业号解决8.3/10.3账号关联问题?

在Google paly应用上架的过程中&#xff0c;相信大多数开发者都遇到过开发者账号因为关联问题&#xff0c;导致应用包被拒审和封号的情况。 而众所周知&#xff0c;开发者账号注册或登录的IP地址及设备是造成账号关联的重要因素之一。酷鸟云最新上线的原生IP能有效降低账号因I…

TensorRT基础知识及应用【学习笔记(十)】

这篇博客为修改过后的转载&#xff0c;因为没有转载链接&#xff0c;所以选了原创 文章目录 一、准备知识1.1 环境配置A. CUDA DriverB. CUDAC. cuDNND. TensorRT 1.2 编程模型 二、构建阶段2.1 创建网络定义2.2 配置参数2.3 生成Engine2.4 保存为模型文件2.5 释放资源 三、运…

一键整合,万用万灵,Python3.10项目嵌入式一键整合包的制作(Embed)

我们知道Python是一门解释型语言&#xff0c;项目运行时需要依赖Python解释器&#xff0c;并且有时候需要安装项目中对应的三方依赖库。对于专业的Python开发者来说&#xff0c;可以直接通过pip命令进行安装即可。但是如果是分发给其他的Windows用户&#xff0c;特别是不熟悉Py…

【网络奇幻之旅】那年我与互联网的邂逅

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;网络奇幻之旅 ⭐每日一句&#xff1a;不想留在过去&#xff0c;就要变得更好 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 &a…

SaaS与PaaS平台的区别

目录 一、前言 二、SaaS化与PaaS化平台的区别 三、PaaS化的低代码平台更胜一筹 PaaS优势&#xff1a; 支持PaaS服务的低代码平台 1.私有化部署&#xff0c;为数据安全保驾护航 2.业内领先技术&#xff0c;为开发强势赋能 3.超强集成能力&#xff0c;系统对接无忧 4.源代码交付&…

企业微信获取第三方应用凭证

上一篇介绍了如何配置通用开发参数及通过url回调验证&#xff0c; 本篇将通过服务商后台配置关联小程序应用配置和获取第三方凭证及如何配置企业可信IP。 当然上篇配置的回调设置也不会白费&#xff0c;在下方的指令和数据回调会用到。 第三方应用开发流程 官方企业微信第三方…

v-for 循环数组的某一部分

方法一&#xff1a;使用slice()方法 代码&#xff1a; <template><div><!--循环前三个元素--><span v-for"(item, index) in arr.slice(0, 3)" :key"index a">{{ item }}</span> <br><!--循环前第六个到第九个元…

语义检索系统【全】:基于milvus语义检索系统指令全流程-快速部署版

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

【Android】带下划线的TextView

序言 我们有时候需要一个类似这样的显示&#xff0c;上面是文字&#xff0c;下面是一条线 这样的显示效果是TextView实现不了的&#xff0c;需要我们自己进行修改一下。 实现 创建一个UnderlineTextView&#xff0c;继承系统的TextView class UnderlineTextView(mContext…

LeetCode(23)找出字符串中第一个匹配项的下标【数组/字符串】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 找出字符串中第一个匹配项的下标 1.题目 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 hays…

如何选择适合企业的ERP管理系统

如何选择适合企业的ERP管理系统&#xff1f; 企业业务不断发展和扩大&#xff0c;ERP管理系统已成为企业实现信息化管理、提高工作效率、降低成本的重要工具。然而&#xff0c;市场上ERP管理系统种类繁多&#xff0c;如何选择适合自己企业的ERP管理系统成为了企业面临的难题。本…

大力说企微第一课:企业微信的注册验证和认证

这段时间有好几个朋友问我&#xff0c;怎么用企业微信&#xff0c;还有一些朋友反馈&#xff0c;企业微信使用起来不太方便。 在我的印象中&#xff0c;企业微信确实不如微信那么简单&#xff0c;毕竟用户对象是企业&#xff0c;是企业就有多个部门&#xff0c;就有流程&#x…

自律成就未来:中国人民大学与加拿大女王大学金融硕士项目引领金融精英之路

在这个日新月异的时代&#xff0c;金融行业正以前所未有的速度发展&#xff0c;对金融人才的需求也日益增长。为了培养更多具备专业素养、创新精神和国际视野的金融精英&#xff0c;中国人民大学与加拿大女王大学金融硕士项目应运而生&#xff0c;致力于为学员提供一个全面提升…

如何构建风险矩阵?3大注意事项

风险矩阵法&#xff08;RMA&#xff09;是确定威胁优先级别的最有效工具之一&#xff0c;可以帮助项目团队识别和评估项目中的风险&#xff0c;帮助项目团队对风险进行排序&#xff0c;清晰地展示风险的可能性和严重性&#xff0c;为项目团队制定风险管理策略提供依据。 如果没…

车联网解决方案(车联网设备安装部署案例)

车联网&#xff08;Connected Car&#xff09;是指通过无线通信技术将汽车与互联网连接起来&#xff0c;实现车辆与车辆之间、车辆与道路基础设施之间以及车辆与互联网之间的信息交流和实时控制。车载网关是车联网系统中的核心设备之一&#xff0c;负责将车辆内部的数据传输到云…

[msg_msg] corCTF2021 -- fire_of_salvation

前言 msg_msg 是 kernel pwn 中经常用作堆喷的结构体. 其包含一个 0x30 大小的 header. 但 msg_msg 的威力远不如此, 利用 msg_msg 配合其他堆漏洞可以实现任意地址读写的功能. 程序分析 本题给了源码, 可以直接对着源码看. 并且题目给了编译配置文件, 所以可以直接编译一个…