在Linux和OSX上用唯一的guid替换每个匹配值的文本
我有一个文件夹,里面有一堆文件。在一些文件中有这样一行在Linux和OSX上用唯一的guid替换每个匹配值的文本,linux,bash,macos,sed,Linux,Bash,Macos,Sed,我有一个文件夹,里面有一堆文件。在一些文件中有这样一行 id = "8c09e1ce-56b6-4aa5-8307-8998f507b594" 所有这些ids都是唯一的 我想编写一个命令,为所有ids生成新的唯一值 我有一个sed命令,该命令将匹配原始行's/id=\“[a-zA-Z0-9-]\{36\\\\\\”//g',但我不知道如何动态地使替换工作 有一些类似的StackOverflow问题(),但我无法获得跨OSX和Linux的可靠解决方案,这是我的要求之一。不过,它们都安装了uuid
id = "8c09e1ce-56b6-4aa5-8307-8998f507b594"
所有这些id
s都是唯一的
我想编写一个命令,为所有id
s生成新的唯一值
我有一个sed
命令,该命令将匹配原始行's/id=\“[a-zA-Z0-9-]\{36\\\\\\”//g'
,但我不知道如何动态地使替换工作
有一些类似的StackOverflow问题(),但我无法获得跨OSX和Linux的可靠解决方案,这是我的要求之一。不过,它们都安装了uuidgen
显然,我更喜欢简洁易读的东西。所以我(通过作弊)找到了答案
每个文件只有一个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
如果可以一次性完成,这个问题仍然是一个一般情况。对于使用
sed
的-i
选项进行编辑,没有跨平台语法可以在不创建备份文件的情况下工作,正如我的一篇文章中所解释的(您必须使用-i'
(BSD/macOS)或只使用-i
(GNU),但在创建备份文件时,类似于-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及其变体上都可用uuidgen
- uuidgen的
- 不幸的是,Mawk(Ubuntu的默认Awk)不支持重复表达式,例如
,这就是为什么上面使用了不太具体的{36}
;但是,如果您知道您将只使用BSD或GNU Awk,那么您仍然可以使用+
{36}
- 该命令支持替换每个输入文件中的多个UUID
另一方面:GNU Awk v4.1+允许使用
-i inplace
进行就地更新,类似于Sed的-i
选项,该选项允许使用-exec
执行单个命令查找解决方案,但是BSD Awk和Mawk都不支持它。您提到的ID字符串的预期输出是什么。hey@Inian我想用所有这些文件中的新guid替换guid值,请。另外,您的sed-i'
仅适用于BSD sed,而不适用于GNU sed。请双引号$i
,以确保其值按原样使用。Sed脚本的s
函数调用中的g
选项是不需要的,因为每个输入行最多有一个UUID。