首页 > 解决方案 > 将不同的正则表达式可能性合并为一个

问题描述

是否可以将以下正则表达式合二为一?

cat file.txt | \ 
sed 's/\tNULL\t/\t\\N\t/g' | \
sed 's/^NULL\t/\\N\t/g' | \
sed 's/\tNULL$/\t\\N/g' | \
sed 's/^NULL$/\\N/g'' 

也许要添加另一件事,这是每月超过数十亿行,因此性能是一个考虑因素。

解决方案 benchmark 谢谢大家的建议,perl给我跑最快的。如果您想知道:

[/tmp]$ time cat /tmp/result_w_null.txt > /dev/null
real    0m0.045s
user    0m0.000s
sys     0m0.042s
[/tmp]$ time cat /tmp/result_w_null.txt | sed 's/\<NULL\>/\\N/g' > /dev/null
real    0m5.843s
user    0m2.472s
sys     0m3.852s
[/tmp]$ time cat /tmp/result_w_null.txt | sed 's/\tNULL\t/\t\\N\t/g' | sed 's/^NULL\t/\\N\t/g' | sed 's/\tNULL$/\t\\N/g' | sed 's/^NULL$/\\N/g' > /dev/null
real    0m7.078s
user    0m7.148s
sys     0m4.963s

#Suggestions:
[/tmp]$ time cat /tmp/result_w_null.txt | awk -F'\t' -v OFS='\t' '{for (i=1;i<=NF;i++) if ($i=="NULL") $i="\\N"}1' > /dev/null
real    0m20.196s
user    0m14.876s
sys     0m7.145s
[/tmp]$ time cat /tmp/result_w_null.txt | awk -v RS='(^|[\t\n])NULL(\tNULL)*([\t\n]|$)' '{ gsub(/NULL/, "\\N", RT); ORS=RT} 1' > /dev/null
real    0m10.611s
user    0m8.743s
sys     0m3.754s
[/tmp]$ time cat /tmp/result_w_null.txt | sed -E ':a; s/(\t|^)NULL(\t|$)/\1\\N\2/g; ta' > /dev/null
real    0m9.673s
user    0m5.723s
sys     0m5.678s
[/tmp]$ time cat /tmp/result_w_null.txt | perl -pe 's/(?:\t|^)\KNULL(?=\t|$)/\\N/g' > /dev/null
real    0m4.452s
user    0m3.237s
sys     0m2.288s

标签: regexsedregex-group

解决方案


这是另一种 gnu-awk 解决方案:

cat file

abc   NULL  foo
NULL  bar
xyz   NULL
pqr   mnop
NULL

gnu-awk与自定义一起使用RS

awk -v RS='(^|[\t\n])NULL(\tNULL)*([\t\n]|$)' '{
gsub(/NULL/, "\\N", RT); ORS=RT} 1' file

abc   \N    foo
\N    bar
xyz   \N
pqr   mnop
\N

推荐阅读