jq正则表达式用法(正则表达式语法大全)

正则表达式(regex or regexp) 通过检索特定模式的一个或多个匹配(即特定的ASCII或者unicode字符序列 ),从任何文本中提取信息,这是非常有用的。
jq正则表达式用法(正则表达式语法大全)

应用范围:解析、替换字符串,数据格式转换,以及网页抓取。

有趣的是,一旦你学会了它的语法,几乎可以在所有编程语言中使用这个工具(JavaScript, Java, VB, C #, C / C , Python, Perl, Ruby, Delphi, R, Tcl, and many others),它们之中只有微小的区别。

让我们来看看一些例子和解析。

基本语法边界匹配??—?? ^ and $

^The 匹配任何以The开始的字符串

end$ 匹配任何以End结尾的字符串

^The end$ 准确地匹配字符串 (The开始,End结尾)

roar 匹配任何含有roar的字符串

量词??—?? * ? and {}

abc* 匹配ab后跟零或多次c的字符串 [0, ∞]

abc 匹配ab后一次或多次c的字符串 [1, ∞]

abc? 匹配ab后零次或一次c的字符串 [0, 1]

abc{2} 匹配ab后2次c的字符串

abc{2,} 匹配ab后2次或更多次c的字符串

abc{2,5} 匹配ab后2到5次c的字符串

a(bc)* 匹配a后零次或多次bc的字符串

a(bc){2,5} 匹配a后2到5次bc的字符串

或 — | or []

a(b|c) 匹配a后跟b或c的字符串

a[b|c] 与上述一致

字符类 —??\d \w \s and .

\d 匹配一个数字

\w 匹配一个字符(字母、数字、字符、下划线)

\s 匹配一个空格(包括tabs、换行\n)

. 匹配任何非空字符(不包含换行\n等空字符)

[\s\S] 匹配任何字符

谨慎使用.元字符,因为字符类和否定字符类处理更快、更准确。

\d, \w 和 \s 分别使用 \D, \W 和 \S 表示它们的否定。

比如,\D将匹配与\d相反的字符。

\D 匹配一个非数字的字符

为了正确的理解,你必须使用反斜杠\ 来转义字符^.[$()|* ?{\, 因为它们具有特殊的含义。

$\d 匹配一个$后跟一个数字的字符

注意,你还可以匹配一个不可打印的字符, 如tabs \t, 换行 \n,回车符 \r。

修饰符

我们正在学习如果编写一个正则表达式,但是忘记了一个基本概念:修饰符

正则表达式通常是/abc/这样的形式,其中匹配模式由两个/分隔。我们可以在它们的最后指定一个以下这些值的标志(也可以将它们组合使用)。

g (global): 第一个匹配后不返回结果,在上一次匹配结果之后继续检索,最后返回所有匹配项(全局匹配)。m (multi-line):启用时^和 $ 将匹配行的开头和结尾,而不是整个字符串。i (insensitive): 使整个表达式不区分大小写(for instance /aBc/i would match AbC)

es6新增

y (sticky):作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配结果的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就行,而y修饰符会确保匹配从剩余位置的第一个位置开始,这也就是“粘连”的涵义。

vars=’aaa_aa_a’;varr1=/a /g;varr2=/a /y;r1.exec(s);//[‘aaa’]r2.exec(s);//[‘aaa’]r1.exec(s);//[‘aa’]r2.exec(s);//nullvarr=/a _/y;//tryagainr.exec(s);//[‘aaa_’]r.exec(s);//[‘aa_’]r.sticky//true

u (Unicode):“Unicode”模式,用来正确处理大于\uFFFF的Unicode字符。也就是说,可以正确处理4个字节的UTF-16编码。

vars=’??’;/^.$/.test(s);//false/^.$/u.test(s);//true

s:匹配意字符,我们知道点(.)特殊字符代表任意字符,但是“行终止符”除外(eg.\n,\r,行分割符,段分隔符),s修饰符可包含所有,这被称为dotAll模式,即点(dot)代表一切字符。

vars=’??’;/.*/s.test(s);//true中级语法分组和捕获—??()

a(bc) 括号为创建一个值为bc的捕获组

a(?:bc)* 使用?:禁用捕获组(非捕获组)

要理解?:则需要理解捕获分组和非捕获分组的概念:

()表示捕获分组,()会把每个分组里的匹配的值保存起来,使用$n(n是一个数字,表示第n个捕获组的内容);

(?:)表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来。

es6新增

a(?< foo >bc) 使用?<foo>给这个捕获组命名。

如果为捕获组命名(使用?<foo>), 我们将能够使用匹配结果的groups中查找捕获组的值,键值就是组名。

当我们从字符串或者数据中提取信息的时候,此运算符非常有用。在使用多个捕获组匹配数据时,

我们将使用匹配结果的索引来访问它们的值($n),也可以具名组groups.<name>访问

varstring=’1999-12-31′;constmatchObj=string.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);//[“1999-12-31″,”1999″,”12″,”31″,index:0,input:”1999-12-31″,groups:{day:”31″,month:”12″,year:”1999”}]constnewStr=string.replace(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,’$<day>/$<month>/$<year>’)//31/12/1999constnewStr2=string.replace(/(\d{4})-(\d{2})-(\d{2})/,’$3/$2/$1′)//31/12/1999//在正则表达式内部也可以使用“具名组匹配”\k<组名>constRE_TWICE=/^(?<word>[a-z] )!\k<word>$/RE_TWICE.test(‘abc!abc’)//trueRE_TWICE.test(‘abc!ab’)//false中括号—??[]

[abc] 匹配a或b或c, 等同于a|b|c

[a-c] 与上述一致

[a-fA-F0-9] 匹配一个十六进制字符,不区分大小写。

[0-9]% 匹配一个%前为0到9的字符串

[^a-zA-Z] 匹配一个没有从a-z或者A到Z的字母。这种情况下,^用作表示否定。

需要注意的是,在中括号表达式中,所有特殊字符(包括反斜杠\)都会失去它们特殊的功能,因此,不要使用“转义”功能

贪婪和懒匹配(Greedy and Lazy match)

量词( * {})是贪婪的匹配,所以它们会尽可能地通过提供的文本扩展匹配。

例如,使用<. > 来匹配 <div>simple div</div>,它会返回整个文本<div> simple div</div>

为了仅匹配一个div标签,我们可以使用?来使它lazy match

<. ?> 匹配<和>内包含的一个或者多个字符,根据需要进行扩展。

那么,更好的正则方案应该避免使用., 赞成使用更严格的模式:

<[^<>] > 匹配<和>内包含的任何字符。高级语法边界??—??\b and \B\babc\b abc前后都无字符, 即执行仅限整个单词匹配

\b 表示边界(类似于^和$)的位置,其中一侧是单词字符(如\w),而另一侧不是单词字符(例如,它可能是字符串的开头或空格字符 eg: \b123)。

它同样有否定,\B。这匹配\b所有不匹配的位置,如果我们找到完全被单词字符包围的匹配模式, 则可以匹配。

\Babc\B 执行abc左右都被字符包围匹配返回引用—??\1

([abc])\1 使用\1返回与第一个捕获组相同的匹配项进行匹配 == ([abc])([abc])

([abc])([de])\2\1 与上述一致,使用\2,\1返回与第二个捕获组,第一个捕获组相同的匹配项进行匹配 == ([abc])([de])([de])([abc]) , 以此类推

(?< foo >[abc])\k< foo > 我们将名称foo放入捕获组中,可以用\k引用它,结果与第一个正则一致 == ([abc])([abc])

前瞻(前置断言)和后瞻(后置断言)—??(?=) and (?<=)

firefox 目前不兼容,遇到过一次,请注意

d(?=r) 仅当d后跟r时才匹配d,但r不会成为整个正则表达式的一部分

(?<=r)d 仅当d前为r时才匹配d,但r不会成为整个正则表达式的一部分

你当然也可以使用否定运算符。

d(?!r) 仅当d后不是r时才匹配d,但r不会成为整个正则表达式的一部分

(?<!r)d 仅当d前不是r时才匹配d,但r不会成为整个正则表达式的一部分

用法介绍

注:pattern 为RegExp的实例, str 为String的实例

用法说明返回值regexp.test(str)判断str是否包含匹配结果包含返回true,不包含返回falseregexp.exec(str)根据regexp对str进行正则匹配返回匹配结果数组,如匹配不到返回null —与match的区别在于返回匹配信息更全str.match(regexp)根据regexp对str进行正则匹配返回匹配结果数组,如匹配不到返回nullstr.replace(regexp, newSubStr \ function)根据regexp / string对str进行正则匹配,把匹配结果替换为newSubStr \ function 的返回值返回替换后的字符串【原字符串不变】str.search(regexp)根据regexp对str进行正则匹配返回第一次匹配的位置str.split(regexp)以regexp为分隔符,对str切割为数组返回切割后的数组test/exec 注意事项

如果正则表达式设置了全局标志 /g,test() 的执行会改变正则表达式 lastIndex 属性。连续的执行 test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,(exec() 同样改变正则本身的 lastIndex 属性值).

下面的实例表现了这种行为:

constdigits=/\d /g;digits.test(“Helloworld!123”);//truedigits.test(“321”);//falsedigits.test(“321”);//true

你可以这样 hack:

constdigits=/\d /g;digits.test(“Helloworld!123”);//truedigits.lastIndex=0;digits.test(“321”);//truedigits.lastIndex=0;digits.test(“321″);//true

详情参考:MDN

replace详解语法str.replace(regexp|substr,newSubStr|function)

参数

a:匹配项

b:匹配的捕获组

若无捕获组则无此参数,若多个捕获组则多个参数 b,c,d,e…;

若一个捕获组重复多次,则该捕获组的参数为最后一次匹配结果。例如:(\d)

c:匹配项在原字符串中的索引

d:原字符串

最后两个参数永远为 匹配项索引和原字符串

regexp (pattern)

一个RegExp对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。

substr (pattern)

一个要被 newSubStr 替换的字符串。其被视为一整个字符串,而不是一个正则表达式。仅仅是第一个匹配会被替换。

newSubStr (replacement)

用于替换掉第一个参数在原字符串中的匹配部分的字符串

function(a, b, c, d) (replacement)

一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。

如果你对 replace 还有困惑,可以看看下面的例题

总结

正如您所见,正则表达式应用领域很广,我确信你的开发生涯中至少见过一次以上规则,下面是它的应用列表:

数据验证(例如,检查时间字符串的格式是否正确)数据抓取(尤其是网络抓取,查找包含特定单词集的所有页面,最终按特定顺序排列)数据包装(将数据从“原始”格式转换为其他格式)字符串分析(例如,捕获所有url get参数,捕获一组括号内的文本)字符串替换(例如,即使在代码会话中使用一个公共IDE来将Java或C类)转换为相应的JSON对象{–替换“;”与“,”使其为小写,避免类型声明等)。语法高亮、文件重命名、packet sniffing和许多其他涉及字符串的应用程序(其中数据不需要是文本的)

Have fun and do not forget to recommend the article if you liked it ??

附录:replace例题将下面两处空缺补全://define(function(window){functionfn(str){this.str=str;}fn.prototype.format=function(){vararg=____;returnthis.str.replace(____,function(a,b){returnarg[b]||”;})};window.fn=fn;})(window);//use(function(){vart=newfn(‘<p><ahref=”{0}”>{1}<a><span>{2}</span></p>’);console.log(t.format(‘http://www.yonyou.com’,’yonyou’,’Welcome’));})();//这里就不给答案了,如果你理解了replace用法,这太easy了。通过正则将 87654321 整数转为 货币 $87,654,321’87654321′.replace(/(\d) ?(?=(\d{3}) (?!\d))/g,function(a,b,c,d){returnd<2?(“$” a “,”):(a “,”);})//$87,654,321//请深入理解replace和正则后再理解该题’87654321′.replace(/(\d{1,3})(?=(\d{3}) $)/g,function(a,b,c,d){returnd<2?(“$” a “,”):(a “,”);})//$87,654,321’87654321′.replace(/\d{1,3}(?=(\d{3}) $)/g,’$&,’)//$&为匹配项;$1,$2…为捕获组//87,654,321密码强度正则,最少6位,包括至少1个大写字母,1个小写字母,1个数字/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])^[0-9A-Za-z]{6,}$/.test(‘w44Y4S’)//前面三个前置断言,针对开头^项的约束/^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])/.test(‘w44sYw’)参考资料Regex tutorial??—??A quick cheatsheet by examples正则表达式中?=和?:和?!的理解[ JS 进阶 ] test, exec, match, replaceES6标准入门(第3版)—— 阮一峰A regular expression surprise in JavaScript

发表评论

登录后才能评论