近期的一些零碎知识点整理


=Start=

缘由:

简单整理记录一下近期想到的一些知识点,结构比较零散,但是内容觉得还比较重要,所以专门开一篇文章记录一下,方便后面有需要的时候参考和继续补充。

正文:

参考解答:

正则表达式的“非捕获”和“正负向环视/预查”

用Hive SQL进行正则匹配和提取
regexp_extract(reflect("java.net.URLDecoder", "decode",query_string,"UTF-8"), 'keywords=([^&]+)&?', 0) as keywords, --达到预期
regexp_extract(query_string, 'keywords=([^&]+)&?', 0) as keywords_raw, --达到预期
regexp_extract(query_string, 'keywords=(.+)&?', 0) as keywords_raw2, --不达预期
regexp_extract(query_string, 'keywords=(.{1,})&?', 0) as keywords_raw3, --不达预期

-- 结果抽样
keywords=IT&    keywords=IT&    keywords=IT&pageNum=1&pageSize=30   keywords=IT&pageNum=1&pageSize=30   keywords=IT&pageNum=1&pageSize=30
        keywords=&pageNum=1&pageSize=30 keywords=&pageNum=1&pageSize=30 keywords=&pageNum=1&pageSize=30
keywords=安全&    keywords=%E5%AE%89%E5%85%A8&    keywords=%E5%AE%89%E5%85%A8&pageNum=1&pageSize=30   keywords=%E5%AE%89%E5%85%A8&pageNum=1&pageSize=30   keywords=%E5%AE%89%E5%85%A8&pageNum=1&pageSize=30
简单整理:
1. 对于请求参数内容的提取(有较为固定的分隔符,比如&),可以使用非特定字符([^&])的方式来替代点(.)
2. 还有就是在上面操作的基础上,不要再(.+?)或是(.*?)这种非贪婪的方式了,会导致拿到的结果不全
3. 最好就是( keywords=([^&]+)&? )这种方式,不容易误匹配,也不容易漏掉有效信息
HIVE SQL中的非空查找函数
非空查找函数 : COALESCE
语法: COALESCE(T v1, T v2, …)
返回值: T
说明:  返回参数中的第一个非空值;如果所有值都为NULL,那么返回NULL

hive> select COALESCE(null,'100','50');
100
正则表达式-非捕获匹配
字符描述
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。

不要让稻草压死骆驼。每使用一个普通括号()而不是非捕获型括号(?:…),就会保留一部分内存等着你再次访问。这样的正则表达式、无限次地运行次数,无异于一根根稻草的堆加,终于能将骆驼压死。养成合理使用(?:…)非捕获匹配的习惯

默认的多选分支『(…|…)』使用的括号是会捕获文本的,也就是说,括号内的表达式真正匹配成功的文本会记录下来,匹配完成之后可以提取出来。但许多时候,我们需要的只是整个表达式的匹配,而不关心“匹配时到底选择的哪种可能情况”,在这种情况下,我们稍加修改,使用“不捕获文本的括号”,可以提高效率。不捕获文本的写法也很简单,只是在开扩号之后加上字符『?:』,也就是『(?:…|…)』。这样做虽然繁琐点,但效率有保障,阅读起来也不困难,我推荐养成这种习惯,只要用到了括号,就想想是否真的要捕获括号内表达式匹配的文本,如果不需要,就是用不捕获文本的括号

正则表达式-环视/预查
字符描述
(?=pattern)正向预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95
(?!pattern)负向预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95

正则表达式的环视是什么——环视顾名思义就是「环顾四周,向左看看向看看,找一个合适的位置」。环视「匹配的是一个位置而不是字符,这点尤为重要」。

首先解释一下什么是「顺序环视」,什么是「逆序环视」。因为正则表达式的匹配过程是从左到右的,所以如果我们要「判断一个位置的右边满不满足某个条件,这就叫顺序环视」。如果我们「判断一个位置的左边满不满足某种条件的话,这就叫做逆序环视。」

你可能会觉得上面这个正则表达式有点难记,首先我们需要知道「环视都是以(?作为开头的,然后接下来的一到两个符号表明是那种环视,再然后就是需要满足的条件,最后是一个)表示结束。(?=条件)可以这样理解,?表示疑问,=表示是否满足匹配。也就是当前位置是否满足给出的条件。」

  1. 肯定的顺序环视 -> (?=李四)

假如你现在是一名叫张三的学生,现在是体育课需要大家排个队,你记性不好忘记了自己之前的位置,但是你还记得你的后面是李四。所以这个时候你肯定「先找到李四,然后站在他的前面就可以了」。所以你这个选择背后的逻辑是,「我站的这个位置后面需要是李四才可以」。如果我们使用正则表达式来表示这个位置的话,那就是(?=李四),这就表示了你想要找的位置。

  1. 否定的顺序环视 -> (?!李四)

假如你现在是一名叫张三的学生,现在是体育课需要大家排个队,但是你不想让李四站在你的后面,因为他总是喜欢用中性笔在你的后背上乱涂乱画。所以这个时候你会怎么选择位置呢?你肯定先看一个位置,只要这个位置的后面不是李四就可以了。「因为就算李四在你前面也无所谓,毕竟他不能画你的后背了。」

所以你做这个选择背后的逻辑是,「只有你站的这个位置后面不是李四才可以」。

上面这个位置可以用正则表达式(?!李四)来表示,作为程序开发者,我们对!很熟悉,在这里也是同样的意思。「表示不能够满足后面的条件。」

  1. 肯定的逆序环视 -> (? (? (?<=\d)(?=(\d{3})+$)

数字千分位的处理。当我们使用正则表达式去解决问题的时候,第一件事情就是需要明确解决的是一个什么问题。对于这个问题来说,我们要解决的问题是匹配一些位置。什么位置?就是一个数字,「从后向前数,每隔三个数字的位置,并且每个位置的左边都需要有数字。」

当我们明确了我们需要解决的问题之后,我们就可以写我们的正则表达式。首先写一个能够匹配每隔三个数字的位置。这个比较容易我们可以使用「肯定的顺序环视」,(?=\d{3})应该是我们比较容易想到的。这个正则表示的意思就是「匹配一个位置,这个位置的后面需要是三个数字」。

(?=a) 前面有a
(?!a) 前面没有a

因为正则表达式的匹配过程是从左到右的,所以如果我们要「判断一个位置的右边满不满足某个条件,这就叫顺序环视」。如果我们「判断一个位置的左边满不满足某种条件的话,这就叫做逆序环视。」
正则表达式中的不匹配
/^((?!PART).)*$/ #匹配不包含字符串 PART 的行
/^(?!PART)/ #匹配不以字符串 PART 开头的行

查找不以baidu开头的字符串 #正则 ^(?!baidu).+$

查找以com结尾的字符串 #正则 ^.*?(?<=com)$
查找以com结尾的字符串 #正则 ^.*?com$

查找不以com结尾的字符串 #正则 ^.*?(?<!com)$

对正则表达式的解释:^.*?(?<!com)$
首先匹配行开头,**然后是 .*? 这个是忽略优先,也就是优先忽略不匹配任何字符**,(?<!com) 这个是一个逆序环视的否定形式,意思是匹配一个位置此位置的前面不能是字符串com,最后是一个行结束。对于www.123.com来说,首先匹配行首,接着匹配w后面的位置,发现前面不是com,所以成功但紧接着要匹配行尾,失败,回溯让.*? 匹配一个w符号,接着(?<com)匹配第二个w后面的位置,发现前面也不是com匹配成功,紧接着要匹配$对应的行尾失败,一直到.*?匹配了www.baidu.com的时候,此时(?<!com)匹配m后面的位置,此时此位置的前面是com匹配直接失败,接着.*?匹配行末尾,(?<!com)匹配$后面的位置,显然这次也失败了,所以整个全局匹配都失败。  www.123.com被排除到匹配之外。这里的.*后面加不加问号结果都一样。


查找不含有if的行 #正则 ^([^f]|[^i]f)+$

排除不含有某字符串的最终方案 #正则 ^(?!.*helloworld).*$
排除不含有某字符串的最终方案 #正则 ^((?!helloworld).)*$ (但效率没有上面那个高)
参考链接:

判断一行中不包含特定关键字的正则表达式(Regular expression to match a line that doesn’t contain a word?)
https://stackoverflow.com/questions/406230/regular-expression-to-match-a-line-that-doesnt-contain-a-word

利用正则表达式排除特定字符串
http://www.cnblogs.com/wangqiguo/archive/2012/05/08/2486548.html

正则表达式里字符串”不包含”匹配技巧
http://www.aqee.net/post/regular-expression-to-match-string-not-containing-a-word.html

距离弄懂正则的环视,你只差这一篇文章 #nice
https://mp.weixin.qq.com/s/VqiZ6fVL20sJ8NUoQJjm2g

常用的正则表达式
https://ixyzero.com/blog/regex2.html

由“正则表达式中的与或非”想到的
https://ixyzero.com/blog/archives/2059.html

=END=


《 “近期的一些零碎知识点整理” 》 有 3 条评论

  1. `
    (?:pattern)
    非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(I)”来组合一个模式的各个部分是很有用。例>>如”industr(?:y|ies)”就是一个比”industry|industries”更简略的表达式。

    (?=pattern)
    非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配”Windows3.1”中的“Windows”。
    预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

    (?!pattern)
    非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。

    (?<=pattern)
    非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配"2000Windows”中的“Windows"”,但不能匹配“3.1Windows”中的“Windows”。

    (?<!pattern)
    非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows”能匹配"3.1Windows”中的"Windows",但不能匹配“2000Windows”中的“Windows””。这个地方不正确,有问题
    `

  2. 正则表达式在前面或者后面不想匹配某字符串的特殊用法
    https://blog.csdn.net/zh515858237/article/details/113877648
    `
    (?:pattern)
    非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(I)”来组合一个模式的各个部分是很有用。例>>如”industr(?:y|ies)”就是一个比”industry|industries”更简略的表达式。

    (?=pattern)
    非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配”Windows3.1”中的“Windows”。
    预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

    (?!pattern)
    非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。

    (?<=pattern)
    非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配"2000Windows”中的“Windows"”,但不能匹配“3.1Windows”中的“Windows”。

    (?<!pattern)
    非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows”能匹配"3.1Windows”中的"Windows",但不能匹配“2000Windows”中的“Windows””。这个地方不正确,有问题
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注