如何使用grep、xargs、sed单次遍历批量替换文件中的UUID提升效率
优化方案
你原方案的性能瓶颈在于每匹配到一个UUID就触发一次sed原位写入,文件有多少个UUID就会重写多少次,大文件场景下效率极低。以下两种方案均仅需单次遍历文件、单次写入即可完成全部替换,性能提升非常明显:
方案1:Perl单行命令(最推荐,适配绝大多数环境)
# GNU环境(Linux)直接运行,会直接修改原文件 perl -i -pe 's/([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12})/lc `uuidgen -t`/gei' /home/username/sql_inserts_with_uuid.sql # 如需备份原文件,修改为-i.bak,会自动生成后缀为.bak的原文件备份 perl -i.bak -pe 's/([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12})/lc `uuidgen -t`/gei' /home/username/sql_inserts_with_uuid.sql # macOS环境运行需在-i后加空字符串 perl -i '' -pe 's/([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12})/lc `uuidgen -t`/gei' /home/username/sql_inserts_with_uuid.sql
参数说明:
-i:启用原位编辑模式- 正则末尾的
e标记:将替换段内容作为系统命令执行,每次匹配到旧UUID就生成一个新的UUID - 正则末尾的
i标记:匹配UUID时忽略大小写 - 正则末尾的
g标记:每行匹配全部符合规则的UUID,而非仅替换第一个 lc:将uuidgen默认输出的大写UUID转为小写,和原文件格式对齐,不需要小写可删除该字段
方案2:Awk实现(无Perl环境时使用)
awk ' BEGIN { uuid_regex = "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}" } { while (match($0, uuid_regex, matched)) { "uuidgen -t" | getline new_uuid close("uuidgen -t") sub(matched[0], tolower(new_uuid), $0) } print }' /home/username/sql_inserts_with_uuid.sql > tmp_sql && mv tmp_sql /home/username/sql_inserts_with_uuid.sql
该方案全程仅读取原文件一次,全部替换完成后一次性写入新文件再覆盖原文件,同样仅产生一次磁盘写入操作。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

