最近做Python课实验发现正则表达式和它在py中的的标准库re有很多能多琢磨一下的点,遂决定写成一篇小记,以后想复习能再来看看。

名词

因为不同文献书籍对正则表达式的描述有差别,我在这里列出一下我已知的名词表述:

本小记中 其他说法
模式 表达式 / pattern
子模式 子表达式 / 子组 / subpattern
贪婪模式 贪心模式 / greedy mode
非贪婪模式 非贪心模式 / 懒惰模式 / lazy mode
非捕获组 non-capturing groups
向前查找 look-ahead
向后查找 look-behind
字符组 character class

子模式扩展语法

  • look-behind语法问题

    展开阅读

    这一节主要围绕(?<=[pattern])(?<![pattern])两个子模式扩展语法展开。

    s = 'Dr.David Jone,Ophthalmology,x2441 \
    Ms.Cindy Harriman,Registry,x6231 \
    Mr.Chester Addams,Mortuary,x6231 \
    Dr.Hawkeye Pierce,Surgery,x0986'
    pattern=re.compile(r'(?<=\s*)([A-Za-z]*)(?=,)')

    在这个例子中我原本是想寻找字符串中人名的姓氏的,但脑袋一热写了个\s*,跑了一下当即给我返回了错误:

    re.error: look-behind requires fixed-width pattern

    我一会儿没反应过来,国内搜索引擎也没查到个大概。冷静下来后咱注意到了 requires fixed-width pattern 这一句,意思是需要已知匹配长度的模式(表达式),再看一眼前面的look-behind,突然咱就恍然大悟了:

    pattern=re.compile(r'(?<=\s)([A-Za-z]*)(?=,)')

    这样写就没问题了,我们匹配到了所有的姓氏:

    print(pattern.findall(s))
    # ['Jone', 'Harriman', 'Addams', 'Pierce']

    问题出在哪呢?

    所谓look-behind其实就是(?<=[pattern])一类子模式扩展语法。

    • 注意分辨 (?<=[pattern])(?=[pattern])前者是放在待匹配正则表达式 之前的,后者是放在待匹配正则表达式 之后的。

    • 这两个子模式扩展语法的功能是 匹配[pattern]的内容,但在结果中并不会返回这个子模式

    • 我们通过表格来说明一下,功能是如果匹配到了即返回 [pattern2] 匹配 的内容:

      正则写法 正误
      (?<=[pattern1])[pattern2](?=[pattern3])
      (?=[pattern1])[pattern2](?<=[pattern3]) ×
      [pattern4](?<=[pattern1])[pattern2](?=[pattern3])
      [pattern4](?<=[pattern1])[pattern2](?=[pattern3])[pattern5]
      (?<=[pattern1])[pattern2]
      [pattern2](?=[pattern1])

    拿上面的模式(表达式)举例:

    (?<=\s)([A-Za-z]*)(?=,)

    从匹配内容上来说该模式(表达式)其实就是:

    \s([A-Za-z]*),

    如果该模式(表达式)匹配到了内容,返回的 部分 是不包含(?<=\s)(?=,)的匹配内容的:

    [A-Za-z]*

    咳咳,有点偏了,继续讲回来。要匹配的正则表达式(?<=[pattern])后面,所以匹配的时候是往后看的,所以(?<=[pattern])就叫look-behind

    连起来看look-behind requires fixed-width pattern这个错误,意思就是(?<=[pattern])中的待匹配子模式[pattern]宽度一定要能确定

    我们之前的写法(?<=[pattern]*)用了一个元字符 * ,这个元字符代表前面的[pattern]会重复匹配 0次或更多次 ,所以宽度是不确定的,由此导致了报错。


    除此之外,

    (?<![pattern]*)也是look-behind子模式,所以也适用于上面的情况

    • 同样注意分辨 (?<![pattern])(?![pattern])前者是放在待匹配正则表达式 之前的,后者是放在待匹配正则表达式 之后的。

    • 这两个子模式扩展语法的功能是 如果没出现[pattern]的内容就匹配,但在结果中并不会返回这个子模式

    一句话总结:综上,在使用(?<=[pattern]*)(?<![pattern])时,在[pattern]里请不要使用 ? , * , + 这些导致宽度不确定的元字符。

    元字符 功能
    ? 匹配前面的子模式0次或1次,或者指定前面的子模式进行非贪婪匹配
    * 匹配前面的子模式0次或多次
    + 匹配前面的子模式1次或多次

    要好好记住哦~

  • 非捕获组和look-ahead,look-behind的区别

    展开阅读

    在子模式扩展语法中非捕获组(non-capturing group)写作(?:[pattern]),look-ahead是向前查找,look-behind是向后查找,我们列张表:

    英文术语 中文术语 模式
    正向向后查找 positive look-behind (?<=)
    正向向前查找 positive look-ahead (?=)
    负向向后查找 negative look-behind (?<!)
    负向向前查找 negative look-ahead (?!)

    正向负向指的分别是 出现则匹配不出现则匹配

    在上面一节里我们已经谈了一下look-aheadlook-behind,现在又出现个非捕获组。

    非捕获组(?:[pattern])的功能是匹配[pattern],但不会记录这个组,整个例子看看:

    import re
    s = 'Cake is better than potato'
    pattern = re.compile(r'(?:is\s)better(\sthan)')
    print(pattern.search(s).group(0))
    # is better than
    print(pattern.search(s).group(1))
    # than

    Match对象group(num/name)方法返回的是对应组的内容,子模式序号从1开始。group(0)返回的是整个模式的匹配内容(is better than),而group(1)返回的是第1个子模式的内容(than)。

    这里可以发现第1个子模式对应的是(\sthan)而不是(?:is\s),也就是说(?:is\s)这个组未被捕获(没有被记录)

    问题来了,positive look-ahead(正向向前查找)(?=[pattern]) 和 positive look-behind(正向向后查找)(?<=[pattern])出现[pattern]则匹配,但并不返回该子模式匹配的内容,它们和(?:[pattern])有什么区别呢?

    拿下面这段代码的执行结果来列表:

    import re
    s = 'Cake is better than potato'
    pattern = re.compile(r'(?:is\s)better(\sthan)')
    pattern2 = re.compile(r'(?<=is\s)better(\sthan)')
    子模式扩展语法 pattern.group(0) pattern.group(1)
    (?:[subpattern]) is better than 空格than
    (?<=[subpattern]) better than 空格than

    根据上面的结果总结一下:

    1. (?<=[pattern])(?=[pattern])是匹配到了[pattern]不会返回、亦不会记录(捕获)[pattern]子模式,所以在上面例子中整个模式的匹配结果中没有 is空格

    2. (?:[pattern])是匹配到了[pattern]会返回,但不会记录(捕获)[pattern]子模式,所以在上面例子中整个的匹配结果中有 is空格

    3. (?:[pattern])(?<=[pattern])(?=[pattern]) 的共同点是 都不会记录[pattern]子模式(子组),所以上面例子中group(1)找到的第1个组的内容是(\sthan)匹配到的空格than

基本语法相关

  • 非贪婪模式

    展开阅读

    要实现找出字符串中人名姓氏和对应的电话分机码,我会这样写:

    import re
    s = 'Dr.David Jone,Ophthalmology,x2441 \
    Ms.Cindy Harriman,Registry,x6231 \
    Mr.Chester Addams,Mortuary,x6231 \
    Dr.Hawkeye Pierce,Surgery,x0986'
    pattern = re.compile(r'(?<=\s)([A-Za-z]*)(?=,).*?(?<=x)(\d{4})')
    print(pattern.findall(s))
    # [('Jone', '2441'), ('Harriman', '6231'), ('Addams', '6231'), ('Pierce', '0986')]

    主要思路是前面的模式根据空格和逗号先匹配到姓,后面的模式通过x开头和\d{4}匹配到四位电话分机码。

    前面和后面的模式之间我最开始写的是.**元字符会将.的匹配重复0次或多次,然后我们就得到了这样的匹配结果:[('Jone', '0986')](直接一步到位了喂!(#`O′)

    元字符表我好歹还是看了几次的,能制止这种贪婪匹配的符号就是?了,但因为我记得?非贪婪的表现是匹配尽可能短的字符串,再想了一下*元字符重复匹配次数最少不是0次嘛!那这问号可不能加在.*后面了!

    然后我就试了下面几种:

    (?<=\s)([A-Za-z]*)(?=,).*(?<=x)(\d{4})?
    (?<=\s)([A-Za-z]*)(?=,).*(?<=x)?(\d{4})?
    (?<=\s)([A-Za-z]*)(?=,).*(?<=x)?(\d{4})
    (?<=\s)([A-Za-z]*)(?=,).*(?<=x)(\d{4})\s
    (?<=\s)([A-Za-z]*)(?=,).*(?<=x)(\d{4})?\s

    当然这些模式匹配的结果都没能如我愿,实在忍不住了,我还是把中间部分改成了.*?,然后就成了!

    (?<=\s)([A-Za-z]*)(?=,).*?(?<=x)(\d{4})

    想了一下,原来所谓的 匹配尽可能短的字符串 并不是从元字符的功能角度上去说的。

    2between1and3这个字符串来说:

    • 如果我单独写一个.*?进行匹配,就会匹配个寂寞

    • 但如果我在两边加上限定:\d+.*?\d+.*?匹配的内容必须在数字包夹之中),

    • 若为.*贪婪模式,匹配结果会是between1and,但正因为是.*?非贪婪模式,匹配的是 结果字符串宽度更小 的部分 between

    综上,非贪婪指的是在 符合当前模式的情况下 使得最终匹配结果 尽可能地短

    在使用非贪婪模式?符号时要考虑 语境 ,结合上下文去设计功能。

  • 中括号中的元字符

    展开阅读

    写这一节是因为Python课老师说中括号[]里的元字符都只是被当作普通字符来看待了,然鹅,在做实验的时候我发现并不是这样。(・ε・`)

    看看这个匹配单个Python标识符的正则表达式:

    ^\D[\w]*
    # Python标识符开头不能是数字

    这个模式能顺利匹配hello_world2_hey_there这一类字符串。等等,这样的话不就代表\w这种元字符可以在[]中用了嘛!

    我们再试试这些:

    ^\D[z\wza]* # 仍然可以匹配标识符,\w真的起了作用
    ^\D[z\dza]* # 可以匹配 hz2333a,\d也起了作用
    ^\D[z\nza]* # 可以匹配到带换行符的 hz\naaa,\n也起了作用

    很容易能发现\w\s\n\v\t\r一类元字符其实都是可以在中括号[]中正常发挥 元字符的作用 的,其他还有\b等元字符。在中括号中使用他们无非是 有没有意义 的问题,Python并不会报错。

    那么再试试这些吧:

    ^\D[\w+]* # 能匹配到 hello+world
    ^\D[\w+*]* # 能匹配到 hello+world*2
    ^\D[\w+*?]* # 能匹配到 hello+wo?rld*2
    ^\D[(\w+*)]* # 能匹配到 hello+(world)*2
    ^\D[(\w{1,3}+*)]* # 能匹配到 hello+(world)*2,{1,3}
    ^\D[\w$]* # 能匹配到 hello$world
    ^\D[\(\w\*\?\\)\$]* # 能匹配到hello$wor\ld*?

    到了这里,我发现老师说的在[]被当作普通字符的元字符只是一部分罢了,主要是 *?+{}()$ 这些元字符。

    从上面的例子可以看出来,中括号里这些元字符相当于: \*\?\+\{\}\(\)\$

    适用于中括号[]的元字符主要有两个:^ 逆向符,- 范围指定符,比如:

    [^a-z]

    匹配的就是a-z小写字母集之外的随意一个字符。

    总结一下:

    1. \w\s\n\v\t\r,... 一类元字符与其相反意义(例如\w\W)的元字符是完全可以使用在[]中的,无非是有没有意义的问题。

    2. *?+{}()$ ,... 一类其他符号元字符也可以使用在[]中,全被当作 普通字符 对待。

    3. 中括号里用上述的元字符Python都不会报错,请放心~₍₍٩( ᐛ )۶₎₎

  • 子模式引用方法\num

    展开阅读

    教材上列子模式功能时提了一下\num这个用法,但真的只是提了一下:

    此处的num是指一个表示子模式序号的正整数。例如,"(.)\1"匹配两个连续的相同字符

    刚开始我是真没懂这是啥意思,以为是重复引用前面的子模式:

    (\d)[A-Za-z_]+\1

    我试过用这个模式去对12hello3这个字符串进行匹配,然后返回了个寂寞...

    什么gui,这里的\1难道不是重复(\d)再匹配个数字吗?

    随后我改了一下待匹配字符串,就有结果了:

    待匹配Str 匹配结果
    12hello3 None
    12hello1 12hello1
    12hello2 2hello2

    好家伙,原来\num引用的 不是子模式本身,而是 已知子模式的匹配结果

    上面的例子中(\d)第1个子模式,匹配结果如果是 2,那么后面\1的地方也一定要是 2 才会进行匹配,我们再来几个例子:

    (\d)(\d)[A-Za-z_]+\2\1 # 能匹配到 34hello43
    (\d)(\d)[A-Za-z_]+\1world\2 # 能匹配到 34hello3world4
    (\d)(\d)[A-Za-z_]+\1*world\2 # 能匹配到 34hello33333world4

    简单总结:

    1. \num 引用的是对应的子模式匹配的结果,注意这里只能是子模式的序号。

    2. 子模式的序号 从1开始

    3. 如果你需要引用子模式,可以用子模式扩展语法(?<子模式名>)(?=子模式名),例如:

      import re
      s = '34hello33333world4'
      pattern = re.compile(r'(?P<f>\d)(\d)[A-Za-z_]+(?P=f)*world\2')
      print(pattern.match(s).group(0))
      # 能匹配到 34hello33333world4
    4. 在中括号[]\num是没有效果的(和上一节来一波联动)。

re模块修饰符

  • 如何同时使用多个flags

    展开阅读

    re.compilere.searchre.matchre.findall这几个函数都允许修饰符flags作为参数,我们拿re.compile举例:

    import re
    s='''Hello line1
    hello line2
    hello line3
    '''
    pattern=re.compile('^hElLo',re.I)
    print(pattern.findall(s))

    这不得劲啊!我想进行多行匹配又想保证忽略大小写怎么办?( ̄▽ ̄)"

    彳亍,那就这样写!

    pattern=re.compile('^hElLo',re.I | re.M)

    这里的 | 可以称作一个 管道符(似乎是Shell里的叫法)。名字啥的倒无所谓了,使用了这个符号我们就能使用多个标志啦!(虽然通常情况下不会使用超过两个)

    我口味刁钻,我偏不用 | 符,哼!(¬︿¬)

    好啊,没问题啊!那我们先去子模式买点扩展语法!

    在Python里还有个子模式扩展语法可以给整个模块应用多个修饰符(flags),它就是 (?修饰符们)

    pattern=re.compile('(?im)^hElLo') # i->忽略大小写,m->多行匹配
    pattern=re.compile('(?sm)^hElLo') # s->换行符识别,m->多行匹配

    值得注意的是这个子模式扩展语法请最好放在 整个模式的最前面,不然Python会报“不建议”提示:DeprecationWarning: Flags not at the start of the expression.

  • 常用的几个修饰符

    展开阅读
    修饰符 功能
    re.S 让元字符.支持换行符\n
    re.M 对多行进行匹配,对元字符^$有影响
    re.I 匹配时忽略大小写
    re.X 允许模式中有空格和多行,方便阅读

    注:Python3里面没有re.U

    在举例之前先来个记忆方法:

    • re.S和元字符.有关,可以背.S,扩写成单词背成DOT SEARCH,代表这个匹配和点元字符有关。

    • re.I是忽略大小写,直接字面意思背成IGNORE CASE即可。

    • re.M是多行匹配,也可以直接字面意思背成MULTILINE

    • re.X嘛...想不到了,就死背吧(ノへ ̄、)

    先从re.I开始,这一个其实就是让模式忽略大小写去进行匹配

    import re
    s='''Hello line1
    hello line2
    hello line3
    '''
    pattern=re.compile('hElLo')
    print(pattern.findall(s)) # []
    pattern2=re.compile('hElLo',re.I)
    print(pattern2.findall(s)) # ['Hello', 'hello', 'hello']

    re.M的话主要影响了两个元字符的匹配:^开头匹配和$尾部匹配

    普通情况下,^匹配整个字符串的开头,而$匹配的是 单行字符串的末尾 或者 多行字符串中最后一行的结尾

    但使用了re.M后,对于多行字符串来说,^不仅匹配了字符串的开头,还 匹配了每一行的开头;而$也匹配了 每一行的结尾和字符串的结尾,接下来举几个例子:

    import re
    s='''Hello line1
    hello line2
    hello line3
    '''
    print( re.findall('^hElLo\slINe\d',s,re.I) )
    # ['Hello line1']
    print( re.findall('hElLo\slINe\d$',s,re.I) )
    # ['hello line3']
    print( re.findall('^hElLo\slINe\d$',s,re.I) )
    # [] print( re.findall('^hElLo\slINe\d',s,re.I | re.M) )
    # ['Hello line1', 'hello line2', 'hello line3']
    print( re.findall('hElLo\slINe\d$',s,re.I | re.M) )
    # ['Hello line1', 'hello line2', 'hello line3']
    print( re.findall('^hElLo\slINe\d$',s,re.I | re.M) )
    # ['Hello line1', 'hello line2', 'hello line3']

    re.S让元字符 . 能匹配包括换行符\n在内的 所有字符

    默认情况下元字符 . 只能匹配除换行符\n以外的任意字符。

    例子:

    import re
    s='''Hello line1
    hello line2
    hello line3
    '''
    print( re.findall('line(.*)hello',s) )
    # []
    print( re.findall('line(.*)hello',s,re.S) )
    # ['1\nhello line2\n']
    print( re.findall('line(.*?)hello',s,re.S) )
    # ['1\n', '2\n']

    re.X是一个能增加正则表达式可读性的修饰符,让写正则变得更优雅~ ヽ(✿゚▽゚)ノ

    我们先直接上例子:

    import re
    s = 'Dr.David Jone,Ophthalmology,x2441 \
    Ms.Cindy Harriman,Registry,x6231 \
    Mr.Chester Addams,Mortuary,x6231 \
    Dr.Hawkeye Pierce,Surgery,x0986'
    pattern = re.compile(r'(?<=\s)([A-Za-z]*)(?=,).*?(?<=x)(\d{4})')
    print(pattern.findall(s))

    正则越复杂,在单行里的可读性就越差,这不彳亍,我们要优雅!( ̄_, ̄ ),于是可以这样写:

    pattern = re.compile(r'''
    (?<=\s) # 根据空格匹配姓氏大概位置
    ([A-Za-z]*) # 姓氏是由英文字母组成的
    (?=,) # 姓氏后面有个逗号
    .*? # 匹配姓氏和电话分机号之间的内容
    (?<=x) # 找到电话分机号共同前缀x
    (\d{4}) # 电话分机号一律是4位
    ''', re.X)

    就差一个红酒杯了有木有,优雅多了!可读性大幅增加o(*≧▽≦)ツ

    由上面的例子可以看出,re.X忽略了多行模式中的空白、换行和#等字符

    这里放一段官方文档对于re.X的描述:

    Whitespace within the pattern is ignored, except when in a character class, or when preceded by an unescaped backslash, or within tokens like *?, (?: or (?P<...>. When a line contains a # that is not in a character class and is not preceded by an unescaped backslash, all characters from the leftmost such # through the end of the line are ignored.

    也就是说空格的忽略也有例外

    1. 当空格在字符组(character class),也就是中括号[]里的时候,不会被忽略。

      import re
      s = '''Dr.David Jone,Ophthalmology,x2441
      Ms.Cindy Harriman,Registry,x6231
      Mr.Chester Addams,Mortuary,x6231
      Dr.Hawkeye Pierce,Surgery,x0986'''
      # 我们用 不会忽略中括号内的空格 这个特性来匹配上面字符串中的人名,如Dr.David Jone print(re.findall(r'''
      ^[a-zA-Z.]*?
      [\w]* # 中括号里没有空格
      (?=,)
      ''', s, re.X | re.M))
      # 一个都匹配不上 print(re.findall(r'''
      ^[a-zA-Z.]*?
      [ \w]* # 中括号里有空格
      (?=,)
      ''', s, re.X | re.M))
      # 能够匹配上:['Dr.David Jone', 'Ms.Cindy Harriman', 'Mr.Chester Addams', 'Dr.Hawkeye Pierce']
    2. 当模式中的空格前面有转义斜杠\,这个空格不会被忽略。

      import re
      s = '''Dr.David Jone,Ophthalmology,x2441
      Ms.Cindy Harriman,Registry,x6231
      Mr.Chester Addams,Mortuary,x6231
      Dr.Hawkeye Pierce,Surgery,x0986'''
      # 我们用 不会忽略中括号内的空格 这个特性来匹配上面字符串中的人名,如Dr.David Jone
      print(re.findall(r'''
      ^[a-zA-Z.]*?
      # 这儿只有个普通的空格
      [\w]*
      (?=,)
      ''', s, re.X | re.M))
      # 一个都匹配不上 print(re.findall(r'''
      ^[a-zA-Z.]*?
      \ # 这儿有个被转义的空格
      [\w]*
      (?=,)
      ''', s, re.X | re.M))
      # 匹配上了:['Dr.David Jone', 'Ms.Cindy Harriman', 'Mr.Chester Addams', 'Dr.Hawkeye Pierce']
    3. 当空格在*?(?:(?P<...>这种语法里时,不会被忽略。经过测试,我觉得这一条和上一条转义不会被忽略其实是一个道理(官方文档也没写的很详细)。测试中,这样写不会被忽略:

      \ *?
      (?:\ )
      (?P<...>\ )

      很明显能发现实际上还是 空格转义,当然也有可能是我理解错了。

    不管怎样,这样匹配空格的方法在实际操作中肯定是 非常少用 的,别人读这样的正则表达式时一眼望去还真难发现哪个角落有个空格 (#`O′)

    对于#注释符而言情况就要简单多了,在模式中只有两种情况#不会被忽略:

    1. #存在于字符组(character class),也就是中括号[]里的时候。

    2. #被反斜杠\转义。

After All

正则表达式并不是什么时候都用得上的,尤其是很多时候正则的效率相对于字符串处理还真不算好。

但是,在字符串处理写起来非常繁琐的情况下,正则的确也帮我们节省了不少时间,提升了工作效率。

在咱看来,正则表达式SQL语句有一个共性,就是其在其所处的体系中是通式般的存在:正则表达式几乎可以在所有编程语言中进行使用,而SQL语句也可以在标准化关系数据库管理系统中进行使用。

本人文笔不佳,写的可能有点粗糙。希望这篇小记对大家掌握正则表达式有一定的帮助,感谢各位的耐心阅读。( ゚∀゚) ノ♡

如果后面我在学习Python正则表达式的时候有了新的可记录的点,我会继续更新在这篇文章中。

To be continued...

Python正则表达式使用小记的更多相关文章

  1. Python 正则表达式入门(中级篇)

    Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...

  2. Python正则表达式中的re.S

    title: Python正则表达式中的re.S date: 2014-12-21 09:55:54 categories: [Python] tags: [正则表达式,python] --- 在Py ...

  3. Python 正则表达式入门(初级篇)

    Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...

  4. python正则表达式re

    Python正则表达式: re 正则表达式的元字符有. ^ $ * ? { [ ] | ( ).表示任意字符[]用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字符集,对于字符集中的字符可 ...

  5. Python正则表达式详解

    我用双手成就你的梦想 python正则表达式 ^ 匹配开始 $ 匹配行尾 . 匹配出换行符以外的任何单个字符,使用-m选项允许其匹配换行符也是如此 [...] 匹配括号内任何当个字符(也有或的意思) ...

  6. 比较详细Python正则表达式操作指南(re使用)

    比较详细Python正则表达式操作指南(re使用) Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式.Python 1.5之前版本则是通过 regex 模块提供 E ...

  7. Python正则表达式学习摘要及资料

    摘要 在正则表达式中,如果直接给出字符,就是精确匹配. {m,n}? 对于前一个字符重复 m 到 n 次,并且取尽可能少的情况 在字符串'aaaaaa'中,a{2,4} 会匹配 4 个 a,但 a{2 ...

  8. python正则表达式 小例几则

    会用到的语法 正则字符 释义 举例 + 前面元素至少出现一次 ab+:ab.abbbb 等 * 前面元素出现0次或多次 ab*:a.ab.abb 等 ? 匹配前面的一次或0次 Ab?: A.Ab 等 ...

  9. Python 正则表达式-OK

    Python正则表达式入门 一. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分. 正则表达式是用于处理字符串的强大工具, 拥有自己独特的语法以及一个独立的处理引擎, 效率上 ...

随机推荐

  1. 告别Kafka Stream,让轻量级流处理更加简单

    一说到数据孤岛,所有技术人都不陌生.在 IT 发展过程中,企业不可避免地搭建了各种业务系统,这些系统独立运行且所产生的数据彼此独立封闭,使得企业难以实现数据共享和融合,并形成了"数据孤岛&q ...

  2. Promise源码实现与测试

    const PENDING = 'pending', FULFILLED = 'fulfilled', REJECTED = 'rejected' class MyPromise { construc ...

  3. Park-2018论文

    太阳射电图:Solar magnetograms, EUV images, GOES X-ray flux data. Magnetograms:    http://solar-center.sta ...

  4. 在Ubuntu18.04安装docker之后,以登陆用户身份执行docker pull jenkins,报错:connect: permission denied

    Using default tag: latest Got permission denied while trying to connect to the Docker daemon socket ...

  5. 通过JMETER后置处理器JSON Path Extractor插件来获取响应结果

    学生金币充值接口:该接口有权限验证,需要admin用户才可以做操作,需要添加cookie.cookie中key为登录的用户名,value从登录接口中获取,登陆成功之后会返回sign. 通常做法是在HT ...

  6. LR进行内外网附件上传并发——实践心得

    刚开始接触LR的时候,做了一次内外网附件上传的并发测试,比较简单,但当时理解有些欠缺.以下为当时的实践心得: 1.分内外网测试的意义: 内网测试主要看负载压力情况等,外网测试主要考虑网络带宽.网络延时 ...

  7. pyqt5实现窗口跳转并关闭上一个窗口

    关键在于要定义一个关闭窗体的函数colsewin() 然后将按键与该函数连接(connect)在一起即可 import sys from PyQt5.QtWidgets import QMainWin ...

  8. 利用griddata进行二维插值

    有时候会碰到这种情况: 实际问题可以抽象为 \(z = f(x, y)\) 的形式,而你只知道有限的点 \((x_i,y_i,z_i)\),你又需要局部的全数据,这时你就需要插值,一维的插值方法网上很 ...

  9. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...

  10. CF1082E Increasing Frequency (multiset+乱搞+贪心)

    题目大意: \(给你n个数a_i,给定一个m,你可以选择一个区间[l,r],让他们区间加一个任意数,然后询问一次操作完之后,最多能得到多少个m\) QWQ 考场上真的** 想了好久都不会,直到考试快结 ...