代办事项中一直存在这样一个列表,一直没有完全吸收,这里先列着慢慢消化吧。不过大多数情况下都是直接豆瓣搜索看评价看了,也没有来得及维护这个列表,找个时间整理成豆列吧。
计算机系统与网络
编程通用
算法与数据结构
职业修炼与规划
大师访谈
架构 / 性能
Web 前端
Java 开发
.NET
Python
Android
iOS
PHP
C 语言
C++
机器学习和数据挖掘
数据库
测试
项目与团队
求职面试
编程之外
要给哥弄个 Nexus 5,网上一查有美版的 D820,还有国际版的 D821。顺手做个笔记LG D820 VS LG D821。两个版本的 LG Nexus 5 在几乎所有的配置和外观上都没有任何的区别,主要区别在通讯模块上,一个支持 GSM/CDMA/WCDMA/LTE,而另外一个不支持 CDMA,具体的支持情况外媒梳理如下:
##北美 Nexus 5 版本 (LG D820):
##Nexus 5 国际版本,没有 CDMA (LG D821):
D820 能够兼容 AT&T、T-Mobile 和 Sprint 的 2G、3G 和 LTE 网络;而 D821 则可兼容欧洲、亚洲等其余地区的网络频段。
D820 美版需要破解才能电信 4G,D821 支持联通 4G,中国移动所使用的是特有的频段,不支持
##D820(H)、D820(E)、D820(S) 区别
D820(H)、D820(E)、D820(S) 三者其实硬件都是一样的,就是 RAM 颗粒使用得不一样而已。 D820(H) 是 Skhynix(海力士)的 RAM 颗粒,D820(E) 是 Elpida(尔必达)的 RAM 颗粒,D820(S) 是 Samsung(三星)的 RAM 颗粒。查了下 LG 的内部资料,貌似 D820(S) 故障率最高,无故黑砖的同学警惕是否买到 D820(S) 的机器~
查看 D820(H)、D820(E)、D820(S) 方法~关机后,按音量“-”以及开机键同时开机,然后进 bootloader 查看~
参考:
这个插件顾名思义,就是扩展了 vim 中 .
的功能,有些插件实现的复杂修改(比如修改 surrounding) 用原生的 .
无法实现,而用该插件可以实现。
Plug 'tpope/vim-repeat'
既然提到了 vim.repeat
就不得不提到 vim 的 .
操作。
diw
删除了一个 word,那么可以使用 .
来删除另一个 worddd
删除了一行,那么可以使用 5.
来删除 5 行hello!
,那么使用 ESC 进入 normal 模式,那么移动光标,在另外一个地方使用 .
可以快速输入 hello!
而如果使用 :help repeat
就会发现 vim 支持的 repeat,日常使用的 .
只不过是冰山一角。.
被叫做 single-repeat,vim 还支持
等等复杂的 repeat commands。
vim 中的 multi-repeat 其实日常中也非常熟悉,比如 :2,5g/^$/d
这种类似的命令就被叫做 multi-repeat. 解释一下这个例子,就是从 2 到 5 行中匹配 ^$
(也就是空行) 的内容执行命令 d
(删除)。
恢复到这个命令最原本的模式
:[range]g[lobal]!/{pattern}/[cmd]
这条命令的也是就是在行数范围 range 的行上,匹配 pattern 的行,执行 Ex command(默认是 :p
)
:[range]g[lobal]/{pattern}/[cmd]
这条命令的也是就是在行数范围 range 的行上,不匹配 pattern 的行,执行 Ex command(默认是 :p
)
:[range]v[global]/{pattern}/[cmd]
同 :g!
几点说明:
/
可以使用其他非字母单字节字符来替换,比如使用 \
, "
, |
, 等,这种方式使得可以在 pattern 中直接使用 /
cmd
是 vim 的 Ex cmd,使用 :help ex-cmd-index
来查看:d
delete lines:g
execute commands for matching lines:grep
run ‘grepprg’ and jump to first match:help
:insert
:ls
:m
move lines:new
create a new empty window:w
write to a file:wq
:x
:z
比如替换文本中所有 pat 为 PAT
:g/pat/s//PAT/g
同样也可以使用 :%s/pat/PAT/g
g
命令是一个非常强大的命令,更多的可以参考下一章节的 g
使用。
更为复杂的 repeat ,那就需要使用到 vim 内置的 register 0-9a-zA-z"
,
q{0-9a-zA-z"} " 来开启录制
q " 之后使用 q 来停止录制
@{0-9z-aA-Z".=*+} " 执行 Register 中的内容,`%` 当前文件名,`#` 可选文件名,这两个 Register 不能使用
@@ " 执行上一次
delete all line match pattern
:g/pattern/d
delete all lines not match pattern
:g!/pattern/d
:v/pattern/d
copy all match lines to the end of file
:g/pattern/t$
move all match lines to the end of file
:g/pattern/m$
copy all lines matching pattern to register ‘a’
qaq:g/pattern/y A
说明:
qaq
清空 Register a:help :y
), yank the current line into register A (append to register a)reverse entire file
:g/^/m0
前一天就看到Rumor说Google有一款inbox产品要发布,没想到今天一早就看到+Sundar Pichai 发了一Po 说发布这个产品了。第一时间申请了邀请码,可是到目前为止也没见邀请码的踪影,也就只能从一些介绍,截图,视频中看到一些端倪,也由此写下一些想法。
##改变 Gmail发布已有10年,这十年时间Gmail改变了人们使用邮箱的习惯,而这十年变化的东西太多了,邮箱这一概念早被人说是应该淘汰的东西,时至今日邮箱却依然还是日常生活,工作交流中很重要的一个环节,可是邮箱亟需要变革,不仅是作为用户而言,并且是邮箱服务提供商应该需要思考的问题,越来越多的垃圾邮件,越来越多的不必要的邮件出现在用户的收件箱。而今天Gmail团队给自己的服务一个evolution,虽然Gmail已经在不久前启用了分类服务,能够帮助过滤一些无用的邮件,但可能Gmail团队觉得还不够,他们要以一种智能的方式帮助用户收发邮件—-他们在官方博客上这样说:designed to focus on what really matters. 用户只需要关注他们真正需要关注的。改变总是好的,无论这个改变是好是坏,改变意味着不满足与现有的状态,期望以一种理想的状态而活着。所以无论这个服务是否会像waze失败,最后总会有收获。 图片来自Verge
##UI设计、功能变革 那就来看看这个服务让人耳目一新的功能,首先让人眼前一亮的就是UI的设计,无论是Web还是移动端,简直就是Material Design的推广,靓丽的颜色配合着无比流畅的动画,首先让使用者的体验就很爽朗。其次就是博客中宣传的:Bundles,Highlights,Reminders, Assists, and Snooze,这三个功能构成inbox的主体,虽然Bundles就是Gmail中的不同Tab分类,Highlights应该也就是Gmail中的星,Reminders,Assists,and Snooze也就是Gmail中的工作表,可是inbox给使用者的感受是不一样的,让我想到的第一个词语就是GTD,getting things done. 这个词我第一次接触是在本科上的一门校外选修课上老师讲的。邮箱的作用难道不是这个吗?原来我们转了大大的一圈又回到了邮箱最原始的作用,帮助工作生活交流,Gmail原来一种时间乱糟糟的顺序给我们安排,而inbox是以一种事情重要程度,get more import things done first.
##背后算法 说到inbox这里,就不免让我想起Google Now,想起Andrew Ng的机器学习,Google Now是Google推出的个人助手,机器学习是一门公开课,我们这学期也在学,inbox能够提供这样的一种服务,Google要在背后做的运算是及其大的,如果要做的更加智能要做的或许更多,一封邮件重要与否,一封邮件对于某一个个人重要与否,都需要背后很强大的算法计算得出。而同样你得提供更多的数据,所谓的给予的多,收获的更多。当然这只是我片面的想象,背后的数据谁也不知道,除非你去问Google的employee们。
##inbox展望 inbox作为Gmail的一个革新,无论如何我都是期待的。目前我还没用过还不知道真正的使用体验也就不好说什么了。只是Google各种产品的混乱逻辑也我也弄不清楚了,虽然Gmail一直有工作表这样的功能,但却把GTD的功能做的很烂,虽然之前的keep也有GTD类似的功能,却放在类似记事本一样的笔记类应用中。当然那些产品加上那些功能也不是多此一举,却一时间让人无法选择。我原本以为所谓的inbox应该是所有服务的一个inbox,当然Gmail是最最最重要的一个inbox,而Google+的通知呢?在Web上无处不在的通知难道不应该出现在inbox中?Blogger的评论呢?YouTube制作者的评论呢?或许那死了的Reader还有那个你关注的博客又更新了一篇文章呢?我原本以为的inbox是那样的,最后的结果是我真的想多了。 但转念一想,或许不久Google Now能够给我们提供吧,期待未来。
使用智能手机的朋友会发现,在手机信号旁边或者上面都会有一些奇怪的字母,比如3G、E、H等等,这些字母都代表什么意思呢?哪种网络状态速度最快?下面让我们详细了解一下吧!
G指GPRS,它是GSM移动电话用户可用的一种移动数据业务,GPRS可说是GSM的延续,是2.5G网络。在iPhone手机上显示O;2.5G的速度约为10KB/s
E指EDGE网络,是增强型数据速率GSM演进技术,属2.75G,速度约为20KB~30KB/s
3G指普通3G网络,在国内常见的3G有电信的CDMA2000、联通的WCDMA和移动的TD-SCDMA三种,速度在2-7M;
H见于联通的WCDMA手机上,指3G的升级版HSDPA网络,是3.5G,速度可达14.4M;
H+常见于中国联通的WCDMA手机上,hsdpa的升级版HSPA+,是3.75G,速度可达21M-42M;
从网络速度对比来看,从慢到快依次是 G<E<3G<H<H+
。
日常生活中,在使用手机的过程中,我们常常可以在屏幕的状态栏上方看到网络信号的标识,大概有G/3G/T/E/1X/H/H+这些信号标识,这些标志代表什么含义呢?
G:G是GPRS通用分组无线服务技术(General Packet Radio Service)的简称,它是GSM移动电话用户可用的一种移动数据业务,GPRS可说是GSM的延续。GPRS的传输速率可提升至56甚至114Kbps,理论上资费较为便宜。具有高速数据传输速度10倍于GSM、永远在线、仅按数据流量计费的特点;
E:E是EDGE(Enhanced Data Rate for GSM Evolution)增强型数据速率GSM演进技术的简称,是一种从GSM到3G的过渡技术,GPRS到第三代移动通信的过渡性技术方案(GPRS俗称2.5G, EDGE俗称2.75G.)。现在中国移动的EDGE网络已经基本上覆盖全国,只有一些较为偏僻的地区无法访问,其传输速率在峰值可以达到384kbps,现在比较主流的无线网络传输方式;
T或者(H):T是TD-SCDMA(Time Division-Synchronous Code Division Multiple Access时分同步码分多址)的简称,其是中国提出的第三代移动通信标准(简称3G),也是ITU批准的三个3G标准中的一个以我国知识产权为主的、被国际上广泛接受和认可的无线通信国际标准。现在使用的版本是R4版本,理论下载数值为378.2KB/S。
移动卡的用户在信号不稳定时,手机可以在这些信号中自动转换,使你的手机基本通话要求得以保证不间断。
G:这里不用介绍了,和移动的G是一样的,但是由于联通建的基站比较少,所以网络信号质量很差,大家都不愿意用了;
3G(或者H或者3.5G):HSDPA(High Speed Downlink Packet Access)高速下行分组接入,是一种移动通信协议,亦称为3.5G(3½G),它的下载速度理论呢是可以达到7.2Mbp/s。在国内的三大运营商中,联通的3G是做的最好的,很多人用;
H+:HSPA+的英文全称为 High-Speed Packet Access+,增强型高速分组接入技术,是HSPA的强化版本,最高的下行21Mbps,大部分HSPA+手机基本都是支持5.76Mbps的最高上行速度和21Mbps或者28Mbps的最高下行速度,相比较HSPA的速度更快。总的来说HSPA+比HSPA的速度更快,性能更好,技术更先进,同时网络也更稳定,是目前LTE技术运用之前的最快的网络!其属于联通3.75G网络,当前的联通3G网络覆盖较好。显示H+的时候网速是最快的,理论速率可以达到42Mbp/s的,也就是联通目前畅销的WO卡。
1X:1X即CDMA1x,也就是我们通常所说的电信的2G网络,CDMA1X手机上网的传输速率可达每秒钟144Kb,不过在现在的情况下,1X已经满足不了用户的需求了。不过电信2G(也就是1X)对比其它运营商的G属于是最稳定的,也是表现最好的信号;
3G:3G是指3G信号CDMA2000(EVDO.A),EV-DO是3G CDMA的技术名称,在手机上为了简便显示为3G,它的速率理论上达到3M,但实际上一般只有1.6M左右。它是基于移动网络的多址分发同时提供网络流量,这3家运营商的3G网络信号覆盖最好最广的就是电信的3G信号了,他的实测下载速度峰值可以达到290Kb/s左右,电信卡的资费理论上也比较便宜点;
在玩Ingress之后的很长一段时间内,我觉得如果照片没有地理位置信息是一种缺失,而去年买的 Nikon 单反没有GPS模块,Nikon提供的GPS模块需要单独购买价格不便宜并且携带不方便,于是我找到一种既便宜又简洁的方式可以给照片添加上GPS信息。
需要借助的工具:
具体原理是:按照时间顺序,将手机记录的GPS信息写入相机拍摄的照片中。
具体步骤:
之后GPS信息就被写到照片文件中了。
Java 中和正则相关的工具类都在 java.util.regex
包下,Java 使用了 Nondeterministic Finite Automaton (NFA),之所以称为非确定性是因为当正则匹配给定字符串时,每一个字符都可能和正则匹配多次。这个匹配引擎被广泛的使用在 .NET, PHP, perl, Python, Ruby 中。很多人认为正则处理很快,很强大,但是其实不同正则表达式的写法可能导致消耗的时间和空间相差几十倍甚至上百倍,当在一些移动设备中使用正则时则要更加注意。
在引擎内部,NFA 使用回溯(backtracking) ,通常情况下针对给定的字符串,正则表达式可能有不止一种匹配方式,那么规则匹配引擎则会尽可能匹配所有可能,直到失败。
为了更好的理解 NFA 和回溯,举一个简单的例子,比如有一个正则表达式 sc(ored|ared|oring)x
,而输入的文本是 scared
。
在开始的时候,引擎会查找到 sc
,立即找到匹配的前两个字符,接着会从第三个字符开始匹配 ored
,发现不匹配则会尝试下一个可能 ared
,这个匹配成功,继续匹配后面的 x
,此时发现不成功,那么引擎会回溯回去匹配第三个可能 oring
,同样也没有匹配。那么引擎会回溯到第二个字符开始继续匹配 sc
,直到匹配到字符结尾,然后抛出匹配失败。
在上面的例子中就能看到,NFA 使用回溯来进行规则匹配,上面的例子也非常容易发现回溯的一个问题,就是即使是很简单的例子,也可能导致回溯非常多次。由此可以想象,当回溯失控时对应用程序的性能影响。因此优化正则表达式的一个很重要的部分就是尽量减少回溯的次数。
因为回溯的存在,在遇到现实复杂情况时,正则匹配可能需要花费大量时间来寻找完整的匹配。更糟糕的是,引擎花费大量的时间来匹配从而宣告一次失败,这个时间远比一次成功的匹配来得多。因此需要记住的是,当测试正则表达式的速度时,测试正则匹配不成功的时候,而不是测试成功的匹配。而当测试匹配时,则尽量使用刚刚好匹配的字符串,因为这种字符串花费最长的时间。
当程序中需要不止一次使用相同的正则表达式时,预先编译好后使用。先使用 Pattern.compile()
定义好,而不是直接使用 Pattern.matches()
。matches()
方法内部每一次都会重新编译表达式。
并且记住对于不同的输入字符串,我们可以复用 Matcher
对象,不过要记住调用 reset()
方法。
如果不需要引用括号内容,使用非捕获型括号 (?:PATTERN)
,节省捕获时间,减少回溯使用状态数量。只在必要时使用括号捕获。
比如在 [Ff]
应当使用不区分大小写的匹配而不是字符组
正则表达式提供很多结构(字符组,多选结构,量词等等),很多结构功能存在重叠,做同一件事情可能有不同的表达,这个时候应该选择最适当的结构。比如多选结构和字符组,多选结构完全覆盖了字符组。(a|b|c|d)
和 [abcd]
匹配的文本是一样的,但是多选结构用于处理“可能出现若干表达式”,而字符组是专门用于处理“可能出现若干字符”的,这种情况字符组效率要远远高于多选结构。所以应当选择用 [abcd]
.
正则非常灵活,往往同一个表达式可能匹配多种不同形态的文本,但是如果一个表达式中包含若干”能匹配不同形态文本“的子表达式,那么子表达式能匹配的文本有重叠就可能有效率问题。
比如 a+a+
,再比如 [0-9]+\w+
前后连接部分产生重复匹配问题。
两条规则
regex1*regex2*
(量词不限于*) 的表达式,都要尽力避免 regex1 和 regex2 能匹配相同的内容(regex1|regex2)
的表达式,尽力避免 regex1 和 regex2 匹配相同的内容除非是及其罕见的情况,否则以 .* 开头的正则表达式都应该在最前面添加 ^
或者 \A
如果这个正则表达式在某个字符串的开头不能匹配,那么显然在其他位置它也不能匹配。添加锚点无论是手工添加还是通过优化自动添加都能够配合开头字符 / 字符串 / 字串识别优化,节省大量不必要的工作
在表达式前面独立出 ^ 和 \G
^(?:abc|123)
和 (^abc|^123)
在逻辑上是等价的,但是许多正则引擎指挥对第一个表达式使用 开头字符 / 字符串 / 字串识别优化。所以第一种办法的效率高得多
在表达式结尾独立出 $
确定起止锚点能够提高匹配速度,如果使用了 $
标记结尾,正则引擎会从符合条件的长度开始匹配,而略过目标字符串中其他不关心的字符。
用 xx*
替代 x+
能够暴露必须匹配的 x 同样,用-----{0,2}
代替-{5,7}
。
用 th(?:is|at)
替代 (?:this|that)
,就能暴露出必须的 th
。如果不同的多选分支的结尾部分相同,我们也可以从右面”提取”。例如 (?:optim|standard)ization
。
对于传统 NFA,一旦匹配到结果就会停止。
比如对于想要匹配的 a 或 b 或 c 或 d,使用 [a-d]
而不要使用 (?:a|b|c|d)
。字符组比使用分支条件速度快。
谨慎使用点号,星号,加号这样的元字符,只要能确定范围,就不要用点号。只要能够预测重复范围,就不要使用量词。
正则表达式确实很强大,但是不要过分依赖正则。
最常见的错误就是,只要字符串操作就能完成,但非要用正则。比如判定一个字符串以什么开头,或者什么结尾,或者判断是否包含某一个子串。
我们都知道 log4j 有两种配置文件的语法,本文主要介绍 XML 格式的配置格式。
log4j XML 配置的一些细节记录。
我们都知道日志打印的级别,从低到高依次是 TRACE, DEBUG, INFO, WARN, ERROR and FATAL.
日常使用中经常会看到 root 或者 logger 节点配置 <level value="INFO">
这样的语句,root 节点中也有 priority 的配置
<logger name="com.package">
<level value="WARN" />
</logger>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>
定义了 priority 的 root 只会将 DEBUG 级别及其以上级别的日志发送到 Appender 中。logger 的 level 同理,只会将 WARN 级别和以上的日志发送到 appender 中。
他们的区别只在于 priority 在 root 中用,level 则 logger 中用。
appender 的配置
<appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="Threshold" value="ERROR"/>
</appender>
假设有如下两种情况。
priority value="DEBUG" and param name="Threshold" value="ERROR"
priority value="ERROR" and param name="Threshold" value="DEBUG"
所以两者的最后结果是一致的。组合二者的使用能够更有效率的打印测试环境或者生产环境的日志。
定义不同的 appender ,然后在 logger 中定义多个在 pass 到 appender 即可。
则在定义 logger 时 name 中指定对应的 package name,然后引用对应的 appender。
log4j 不支持不同的 appender 打印到相同的文件中。
从开始接触正则到现在已经过去很多年了,然而依然没有完全学会正则,每一次回顾的时候总是有很多很多的新东西。
什么是正则,看中文非常抽象,而英文 regular expression 就好理解得多,regular expression 它是一个有规律,常规的,经常需要用的表达式,究其根本就是一个用来搜索特定字符串的表达式,这个表达式遵循一定的规律,有自身的逻辑表达,通过这种通用的方式可以写出比较容易理解的搜索语句。
根据维基百科的说明 正则一词是美国数学家 Stephen Cole Kleene 于 1950s 正式使用。而这个概念则是在 1980s 因为 Unix 下文本编辑器工具的使用而变得常见。自此之后正则的语法规则 POSIX 和 Perl 区别。
表示或
gray|grey
表示匹配 gray 或者 grey 两个单词
分组,用来定义边界,或者确定执行顺序
gr(a|e)y
和上面表达等效
常见的定量表达
? 表示前面的字符出现 0 次或者 1 次
* 表示前面的字符出现 0 次或者多次
+ 表示前面的字符出现 1 次或者多次
{n} 表示前面的字符出现 n 次
{m,} 至少 m 次
{m, n} m 到 n 次
通配符 .
可以匹配任何一个字符
字符组 Character Class 是一个比较好理解的,就是一组字符,用方括号来标示,表示匹配其中某一个字符。比如常见的
[aef]
[0-9]
[a-zA-Z]
字符组中的范围表示使用的是 ASCII 编码中的码值,所以不能写成 [9-0]
排除型字符组,在方括号后增加 ^
[^0-9] # 非 0-9
[^ae] # 非 a 或 e
字符组简记法,常见的字符组,比如数字,英文字符组,可以用简单的缩写形式来表示。
\d [0-9]
比如字符组中的 -
还有括号 [
, ]
还有常见的 ^
, $
这些特殊意义的字符都是元字符。如果遇到想要匹配这些特殊的字符就需要转义。
^
$
.
[]
[^]
*
()
{}
\b 单词边界
\d [0-9]
\w 字母数字下划线和汉字
\s 任意空白
当用小括号指定子表达式后,匹配这个子表达式的文本(分组捕获)会自动拥有一个组号,从左到右,分组的左括号为标志,出现的第一个分组为 1,其后 2,3,4 类推。
后向引用则可以利用分组捕获的文本来匹配比如重复的单词
\b(\w+)\b\s+\1\b
其中的 \1
在表示引用前面 (\w+)
括号中捕获的文本,比如 go go 则会被匹配。分组捕获通常用在想要获取匹配字符串中部分子串时使用。
但是在使用捕获时一定要注意,过多的捕获会影响正则表达式的效率,如果不需要捕获则可以使用
(?:exp)
来忽略捕获的内容。
分组还有一些其他的语法
(?<name>exp) 匹配 exp,将捕获的文本放到名字为 name 的组,也可以写成 (?'name'exp)
(?#comment) 注释,无任何作用
了解零宽断言需要分两部分来理解,第一是匹配宽度为 0,第二断言表示满足一定的条件。匹配宽度指的是匹配时占字符宽度,比如在匹配不包含 a 或 b 开头的单词时,如果使用 [^ab]
那么 []
则会占用一个字符宽度。零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西时。
零宽断言的英文是 Lookahead and Lookbehind Zero-Length Assertions 这就好理解很多了,就是正则表达式先要匹配的内容往前或者往后的断言,也就是比如我想要匹配的一串数字必须在 id=
后面就可以使用先行断言
(?=id=)\d+
零宽断言又分四种
(?=exp) 断言自身出现的位置的后面能匹配表达式 exp
(?<=exp) 断言自身出现的位置的前面能匹配表达式 exp
(?!exp) 断言此位置的后面不能匹配表达式 exp
(?<!exp) 断言此位置的前面不能匹配表达式 exp
先行断言,也叫零宽度正预测先行断言 (?=exp)
表示匹配表达式前面的位置
比如,b\w+(?=ing\b)
,匹配以 ing 结尾的单词的前面部分(除了 ing 以外的部分)
注意:先行断言的执行步骤是这样的,先从要匹配的字符串中的最右端找到第一个 ing(也就是先行断言中的表达式)然后再匹配其前面的表达式,若无法匹配则继续查找第二个 ing 再匹配第二个 ing 前面的字符串,若能匹配则匹配
例如: .*(?=ing)
可以匹配 cooking singing
中的 cooking sing
而不是 cook
后发断言,也叫零宽度正回顾后发断言 (?<=exp)
表示匹配表达式后面的位置
例如 (?<=abc).*
可以匹配 abcdefg 中的 defg
注意:后发断言跟先行断言相反,它的执行步骤是这样的:先从要匹配的字符串中的最左端找到第一个 abc(也就是先行断言中的表达式)然后 再匹配其后面的表达式,若无法匹配则继续查找第二个 abc 再匹配第二个 abc 后面的字符串,若能匹配则匹配
例如 (?<=abc).*
可以匹配 abcdefgabc
中的 defgabc 而不是 abcdefg
负向零宽断言 (?!exp)
也是匹配一个零宽度的位置,不过这个位置的“断言”取表达式的反值,同样,负向零宽断言也有“先行”和“后发”两种,负向零宽后发断言为 (?<!exp)
比如说想要匹配文本中所有等号后面的数字,但是就是不想匹配 id=123
这样 id= 开始的数字
(?<!id)=\d+
这四个断言的中文翻译的太烂了,完全不知道说的什么,用英语解释就清晰很多。
Atomic groups 光看字面意思完全无法理解,但是如果举例说明,比如
a(bc|b)c
这是一个普通的分组正则,可以匹配 abcc 或者 abc,但是
a(?>bc|b)c
使用 Atomic groups 之后则只能匹配 abcc 而不能匹配 abc.
Atomic groups 在匹配 abc 时,括号中匹配到 bc 就退出了,而此时无法匹配括号外的 c 则失败了。
Atomic groups 会查找到第一个匹配的子串,然后就退出匹配,也不会回溯。所以如果在一些匹配到第一项,而后面不需要考虑的情况下可以使用 Atomic groups。
比如说字符串 foobarbarfoo
:
bar(?=bar) finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar) finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar finds the 2nd bar ("bar" which does not have "foo" before it)
组合使用:
(?<=foo)bar(?=bar) finds the 1st bar ("bar" with "foo" before it and "bar" after it)
表示匹配 bar 要求前面是 foo 而后面是 bar,那么就匹配第一个 bar 了。
(?=)
Find expression A where expression B follows:
A(?=B)
(?!)
Find expression A where expression B does not follow:
A(?!B)
(?<=)
Find expression A where expression B precedes:
(?<=B)A
(?<!)
Find expression A where expression B does not precede:
(?<!B)A
(?>)
An atomic group exits a group and throws away alternative patterns after the first matched pattern inside the group (backtracking is disabled).
(?>foo|foot)s
applied to foots
will match its 1st alternative foo
, then fail as s
does not immediately follow, and stop as backtracking is disabledA non-atomic group will allow backtracking; if subsequent matching ahead fails, it will backtrack and use alternative patterns until a match for the entire expression is found or all possibilities are exhausted.
(foo|foot)s
applied to foots
will:
foo
, then fail as s
does not immediately follow in foots
, and backtrack to its 2nd alternative;foot
, then succeed as s
immediately follows in foots
, and stop.匹配网页标题
<head>([^<]+)</head>
然后取分组 1
网页图片
<img\s+[^>]*? src=['"]?([^"'\s]+)['"]?[^>]*>
取分组 1
简单版本,不精确
[1-9]\d{14}
[1-9]\d{14}\d{2}[0-9xX]
log4j 可以配置不同的包打印到不同的 appender 中,通过在配置中添加如下配置。
<!-- 这里的 additivity 配置了该 package 下的 appender 是否需要传递到 root , 默认为 true , 造成日志打印两遍 -->
<logger name="com.jutils.appender.LogLevelATest" additivity="false">
<level value="INFO"/>
<appender-ref ref="consoleAppender"/>
</logger>
<logger name="com.jutils.appender.LogLevelBTest" >
<level value="WARN"/>
</logger>
定义 logger 在 name 中指定需要 include 的 package full path,然后在 appender-ref 中指定需要打到的 Appender 中。