使用 grep xargs sed 更有效地在文件中生成 UUID
Posted
技术标签:
【中文标题】使用 grep xargs sed 更有效地在文件中生成 UUID【英文标题】:Use grep xargs sed to regenerate UUIDs in a file more effeciently 【发布时间】:2021-12-24 22:11:43 【问题描述】:我成功地能够用文件中新生成的 UUID 替换 UUID:
FILE=/home/username/sql_inserts_with_uuid.sql
grep -i -o -E "([a-f0-9]8-[a-f0-9]4-4[a-f0-9]3-[89aAbB][a-f0-9]3-[a-f0-9]12)" $FILE | xargs -I sed -i "s//`uuidgen -t`/g" $FILE
但它很慢,因为它会为它生成的每个 UUID 重写文件。有没有更有效的方法来一次重写每个 UUID,而不是一遍又一遍地重写同一个文件?
将此示例数据保存在文件中进行测试:
INSERT INTO fake_table (uuid) VALUES ('812ab76e-43ca-11ec-b54f-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('854f7b36-43ca-11ec-9608-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8a09444a-43ca-11ec-8ae2-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8cd0da58-43ca-11ec-9811-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8f9889c0-43ca-11ec-8bfc-00d8617c2296');
【问题讨论】:
此正则表达式"([a-f0-9]8-[a-f0-9]4-4[a-f0-9]3-[89aAbB][a-f0-9]3-[a-f0-9]12)"
与您的示例不匹配。
生成一批uuid,放入文件中,将'uuid'文件和旧文件传递给awk
进行替换;您需要将输出捕获到临时文件,并在完成后用临时文件覆盖旧文件;或者将一系列sed
脚本转储到脚本文件中,然后传递给sed -f
;不确定使用并行操作更新同一目标文件的好处(竞争条件?混合输出?);似乎并发读/写(同一个文件)会比使用单个进程慢;所述单个进程应针对文件的单个读/写
【参考方案1】:
您可以将awk
与系统调用一起使用以一次性替换它们:
awk '
BEGINpat="[a-fA-F0-9]8-[a-fA-F0-9]4-[0-9][a-fA-F0-9]3-[89aAbB][a-fA-F0-9]3-[a-fA-F0-9]12"
function get_uuid()
cmd = "uuidgen"
cmd | getline uuid
close(cmd)
return uuid
$0~pat
uuid=get_uuid()
sub(pat,uuid,$0)
1
' file.txt
打印:
INSERT INTO fake_table (uuid) VALUES ('473C4331-CC31-4FD0-AE99-37FA7E5F23CF');
INSERT INTO fake_table (uuid) VALUES ('EBEC05AB-4236-4384-AF7A-76D4A0615599');
INSERT INTO fake_table (uuid) VALUES ('23740143-6CC1-41FC-8AE7-038810291026');
INSERT INTO fake_table (uuid) VALUES ('7DBF25AF-4E85-4C55-B8CA-0F6150D5DD3C');
INSERT INTO fake_table (uuid) VALUES ('4365127B-EB46-414E-92D4-B48CC211489E');
使用 GNU awk,您可以替换 inplace。否则,您需要将其输出重定向到一个临时文件,然后 mv
源文件顶部的临时文件。这听起来比actually is 更难。
速度测试:将您的示例文件乘以 10,000 个 UUID 替换,在我的计算机上处理该文件需要 21 秒,如果相同文件没有替换,则需要 26 毫秒。系统调用在效率方面不是免费的,但这可能比你正在做的更快......
【讨论】:
使用 GNU awk,您可以就地进行替换 根据您的链接:“inplace
扩展模拟 GNU sed 的 -i 选项,它执行“就地”编辑每个输入文件的...”如果它像 GNU sed 的“就地”选项,它实际上并不是就地的。它只是创建一个临时文件并重命名它。因此,您不能依赖未更改的 inode 或保持正确的硬链接。【参考方案2】:
在普通的 bash 中:
cat new_uuids
#!/bin/bash
hex='[[:xdigit:]]'
hex3="$hex$hex$hex"
hex4="$hex3$hex"
hex8="$hex4$hex4"
hex12="$hex8$hex4"
pat="$hex8-$hex4-[0-9]$hex3-[89aAbB]$hex3-$hex12"
while IFS= read -r line; do
if [[ $line = *$pat* ]]; then
echo "$line/$pat/$(uuidgen -t)"
else
echo "$line"
fi
done
称之为
./new_uuids < sql_inserts_with_uuid.sql > new_sql_inserts_with_uuid.sql
【讨论】:
我在写类似的东西(但不知道[[:xdigit:]]
)。您不需要在while
循环中进行测试,只需echo
替换就足够了。从 2012 年开始,我的计算机上的速度约为 9 秒。
@Fravadona 正确,但在这种情况下,即使没有替换,uuidgen
也会被调用。这可能是可取的,也可能不是可取的,具体取决于匹配/不匹配行的比率。以上是关于使用 grep xargs sed 更有效地在文件中生成 UUID的主要内容,如果未能解决你的问题,请参考以下文章