正则表达式整理(BRE、ERE、PCRE)

学完正则表达式后,发现vscode的查找替换功能支持正则表达式,经常在vscode上实践,用得也越来越顺手,一度觉得自己的正则表达式玩的挺溜的。

但每每在grepfindvim这些工具中使用正则表达式时,却总有各种问题,在vscode上正常工作的正则表达式突然不起作用,甚至还给报错,不禁让人怀疑人生。直到今天才发现,这些差异是grep等工具所支持的正则表达式与vscode不同引起的。

总的来说,正则表达式可以分为Basic Regular Expressions (BRE)Extended Regular Expressions (ERE)Perl Compatible Regular Expressions (PCRE)三类,其中BRE只支持基本的正则表达式,特殊规则需要使用转义符才能使用;EREBRE的基础上进行扩展,使用特殊规则时无需转义;PCRE支持更多的特殊规则,比如dw等。三者规则上的两个常见差异如下:

  • EREPCRE中,可以直接使用*, +, ?, (, ), {, }, |, .这些字符,但在BRE中,需要在前面加上转义符*, +, ?, (, ), {, }, |, .

  • PCRE支持d, w等特殊规则,在EREBRE中需要用[0-9], [a-Z]来完成;

举个具体的例子,提取文本中的11位数的电话号码,三种正则表达式对应的grep命令分别为:

grep -P 'd{11}' phone_list.txt		# PCRE
grep -E '[0-9]{11}' phone_list.txt	# ERE
grep '[0-9]{11}' phone_list.txt	# BRE

vscode上支持的是PCRE,这是最便捷的一种正则表达式,用起来很方便。grepsed等工具支持的默认方式是BRE,所以当我按PCRE的规则在grep里写BRE的正则表达式时,很可能由于使用的特殊规则不被支持而失效。这也是我在用grep等工具感觉一团乱麻的原因。

grep工具可以通过指定参数以支持不同的类别的正则表达式,比如通过指定-E支持ERE,通过指定-P支持PCRE。但sed工具并不支持PCRE,只支持BREEREfind命令只支持ERE,可以通过find -regex 'your_ere'搜索当前文件夹的匹配文件

如果要更严谨一些,其实正则表达式不仅仅分为BREEREPCRE,还分POSIX BREPOSIX EREGUN BREGUN ERE等,甚至在不同的编程语言中也存在一些差异,上面只是一个大体的介绍。

例子——用sed获取记录中的某个分量的列表并排序

数据内容如下

scene=city_time_num[6], order=000, epoch_num=600, rate-lambda2-rho-alpha-threshold=25.000, 0.500, 0.00100, 0.020, 0.60000, epoch=600, iters=14, avg_psnr=35.411, 35.411, psnr=[33.153154166192095, 34.704279109335964, 37.78742808969121, 35.9988477316099] , avg_ssim=0.9787526391547257, ssim=[0.9487845528918274, 0.9728695331527001, 0.981355757416118, 0.9695059914677088, 1.0, 1.0], mse=4.60813E+02, 9.33541E-01, loss=1.16158E+04, cur_time2023-08-16 21:23:34
scene=city_time_num[6], order=100, epoch_num=600, rate-lambda2-rho-alpha-threshold=25.000, 0.500, 0.10000, 0.020, 0.60000, epoch=600, iters=15, avg_psnr=34.978, 34.978, psnr=[32.844886221882774, 34.20092499707755, 37.721248804834175, 35.145515735352554] , avg_ssim=0.9775971501470594, ssim=[0.9453385577641444, 0.9717984184514672, 0.980794551273793, 0.9676513733929512, 1.0, 1.0], mse=5.13529E+02, 9.33541E-01, loss=1.16236E+04, cur_time2023-08-16 21:56:18
scene=city_time_num[6], order=120, epoch_num=600, rate-lambda2-rho-alpha-threshold=25.000, 0.500, 0.00000, 0.020, 0.60000, epoch=600, iters=19, avg_psnr=34.675, 34.675, psnr=[32.74805443096332, 33.98555600184222, 37.08011284617032, 34.8855425424826] , avg_ssim=0.9768241752875638, ssim=[0.944663846905199, 0.9703824247208576, 0.9793499487053454, 0.9665488313939812, 1.0, 1.0], mse=5.29642E+02, 9.33541E-01, loss=1.17355E+04, cur_time2023-08-17 14:19:49

要提取的数据是avg_psnr,先用sed命令清洗数据,然后用sort命令排序:

$ sed -E 's/.+avg_psnr=([0-9]+.[0-9]+).+/1/' ./best_record.txt | sort -n
34.675
34.978
35.411

Reference

The Different Flavors of Regular Expressions
正则表达式“派别”简述
Regular Expression Engine Comparison Chart