在 Linux 和 OSX 上用唯一的 uuid 替换每个匹配的字符串值
Posted
技术标签:
【中文标题】在 Linux 和 OSX 上用唯一的 uuid 替换每个匹配的字符串值【英文标题】:Replace each matched string value with unique uuid on Linux and OSX 【发布时间】:2017-04-16 20:42:29 【问题描述】:我有一个包含一堆文件的文件夹。在其中一些文件中有这样一行
id = "8c09e1ce-56b6-4aa5-8307-8998f507b594"
所有id
s 都是独一无二的。
我想编写一个命令,为所有id
s 生成新的唯一值
我有一个 sed
命令将匹配原始行 's/id = \"[a-zA-Z0-9-]\36\\"//g'
但我不知道如何动态地使替换工作。
有一些类似的 *** 问题 (like this one),但我无法让解决方案在 OSX 和 Linux 上可靠地工作,这是我的要求之一。不过他们都安装了uuidgen
。
简洁易读的东西显然是首选。
【问题讨论】:
您提到的 ID 字符串的预期输出是什么。 嘿@Inian 我想用所有这些文件中的新 guid 替换 guid 值 【参考方案1】:对于使用sed
的-i
选项进行就地编辑,没有跨平台语法可以创建备份文件,正如我的this answer 中所述(你必须使用 either -i ''
(BSD/macOS) 或 只是 -i
(GNU),但是 with 创建一个备份文件就像-i.bak
确实适用于这两种实现)。
也就是说,无论如何,awk
是完成这项任务的更好工具,因为 Awk 脚本允许按需调用 shell 命令和外部实用程序:
find . -type f -name '*.extension' | while IFS= read -r fpath; do
awk '
BEGIN FS=OFS=" = "
$2 ~ /^\"[a-zA-Z0-9-]+\"$/ "uuidgen" | getline uuid; $2 = "\"" uuid "\""
1
' "$fpath" > "$fpath.tmp" && mv "$fpath.tmp" "$fpath"
done
这假定文件名没有嵌入换行符,这在现实世界中很少引起关注。
该命令仅使用符合 POSIX 标准的 shell 功能、实用程序和选项,但以下情况除外:
uuidgen
实用程序,不过,它可在 Linux 和 macOS 以及 FreeBSD 及其变体上使用。
遗憾的是,Mawk(这是 Ubuntu 的默认 Awk)不支持重复表达式,例如 36
,这就是为什么上面使用不太具体的 +
的原因;但是,如果您知道您将只使用 BSD 或 GNU Awk,您仍然可以使用 36
。
该命令支持在每个输入文件中替换多个 UUID。
附带说明:GNU Awk v4.1+ 允许使用 -i inplace
就地更新,类似于 Sed 的 -i
选项,这将允许单个命令 find
-exec
的解决方案,但 BSD Awk 和 Mawk 都不支持。
【讨论】:
【参考方案2】:所以我想通了(通过作弊)。
每个文件只有一个id
,所以我决定遍历文件并分别为每个文件运行sed
,如下所示:
for i in `find . -name "*.extension" -type f`; do
uuid=$(uuidgen)
sed -i '' -e "s/id = \"[a-zA-Z0-9-]\36\\"/id = \"$uuid\"/g" $i
done
这个问题仍然适用于一般情况,如果可以一次性完成的话。
【讨论】:
请do not usefor
to parse command output。此外,您的sed -i ''
仅适用于 BSD Sed,不适用于 GNU Sed。请双引号 $i
以确保其值按原样使用。不需要 Sed 脚本的 s
函数调用中的 g
选项,因为每个输入行最多有 1 个 UUID。以上是关于在 Linux 和 OSX 上用唯一的 uuid 替换每个匹配的字符串值的主要内容,如果未能解决你的问题,请参考以下文章
linux C语言如何生成uuid(通用唯一识别码Universally Unique Identifier)?
linux C语言如何生成uuid(通用唯一识别码Universally Unique Identifier)?