为什么这个 OSX/BSD/GNU sed 解决方法不起作用

为什么这个 OSX/BSD/GNU sed 解决方法不起作用

因此 sed 的行为会有所不同,具体取决于它是 OSX/BSD 还是 GNU 版本。

OSX 需要

sed -i '' <pattern> <file>

而这适用于 GNU sed:

sed -i <pattern> <file>

所以我有这个:

darwin=false;
case "$(uname)" in
    Darwin*) darwin=true ;;
esac

if $darwin; then
    sedi="sed -i '' "
else
    sedi="sed -i"
fi

然后我尝试在 OSX 上调用它

$sedi "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

除了创建一个名为“Version.java”的备份文件外,它还能正常工作。

我不确定为什么这不起作用,因为如果我从 CLI 显式执行此操作:

sed -i '' "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

它无需创建备份文件即可工作。

有什么想法吗?

答案1

当您扩展sedi变量时,发生的情况是 被作为参数''传递,而不是按预期创建一个空参数。sed

我能看到的最好的方法是让你的sedi变量成为一个数组:

if $darwin; then
    sedi=(sed -i '')
else
    sedi=(sed -i)
fi

并像这样使用:

"${sedi[@]}" "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

否则,我认为将您的参数变成实际的空参数的唯一方法是与您的原始声明一起''使用:eval

eval $sedi '"s/VERSION =.*;/VERSION = \"${lver}\";/g"' Version.java

然而,这是一个有点令人讨厌的解决方案,因为您必须在命令的其余部分添加额外的引号/转义层。此外,eval尽可能避免使用通常是良好(且安全)的做法。

更新

如下所述,创建一个函数就可以了。在同一轨道上, analias可能是最短的方法:

if $darwin; then
    alias sedi="sed -i ''"
else
    alias sedi="sed -i"
fi

使用法简单:

sedi "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

答案2

定义一个换行的 shell 函数sed

case "$(uname)" in
    Darwin*) sed () { command sed -i '' "$@"; } ;;
    *)       sed () { command sed -i "$@"; } ;;
esac

相关内容