我有一个像这样的文件
public class Constants {
public static final String PACKAGE_VERSION = '1.24.0.1';
}
我正在执行脚本
sed -E "/PACKAGE_VERSION/s/\'([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\'/\'1.24.0.2\'/g" force-app/main/default/classes/Constants.cls > temp.cls
mv temp.cls force-app/main/default/classes/Constants.cls
将字符串“1.24.0.1”替换为“1.24.0.2”
这可以用一行来完成吗?我应该使用awk
而不是sed
内联编辑文件吗?
当我尝试执行命令时
sed -iE "/PACKAGE_VERSION/s/\'([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\'/\'1.24.0.3\'/g" force-app/main/default/classes/Constants.cls
创建文件 Constants.clsE,而不是对当前文件进行内联修改,并且新文件没有替换。
当我尝试执行命令时
sed -Ei "/PACKAGE_VERSION/s/\'([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\'/\'1.24.0.3\'/g" force-app/main/default/classes/Constants.cls
我收到一个错误
sed: 1: "force-app/main/default/ ...": invalid command code f
我希望该脚本可以在 MacOS 和 Linux 上运行,而无需更改脚本。
我尝试使用awk
,但我不明白如何使其内联编辑文件?
当我尝试执行以下命令时
awk -v v="$version" '/PACKAGE_VERSION/{gsub(/[0-9]+(.[0-9]+){3}/,v)}1' force-app/main/default/classes/Constants.cls > force-app/main/default/classes/Constants.cls
这使我的文件空白
答案1
不同的实现sed
复制了就地编辑-i
的选项,但不幸的是它们之间具有不同的 API。perl
有些还添加了-E
或-r
来支持(高级)扩展正则表达式(POSIX 或其变体),一些-R
或-P
甚至是为了(非常)高级的类似 perl 的正则表达式(PCRE 或类似),但同样(除此之外-E
将使其成为可能)到 POSIX 标准的下一个版本,并且现在在越来越多的实现中找到),没有什么通用的。
在这里,您不妨使用真实的东西并避免所有这些可移植性问题:
perl -i -pe "s{\bPACKAGE_VERSION\s*=\s*\K'\d+(\.\d+){3}'}{'1.24.0.3'}g" file
答案2
在某些 sed 中(至少自由BSD以及您在 Mac 上获得的那个),该-i
选项需要强制的设置用于备份文件的后缀的参数。您可以在 shell 中编写-i.suffix
, 或,或者不给出后缀。在这些中,or都会将or作为 and 的参数,而不是一个选项。-i .suffix
-i ""
-iE
-i -E
E
-E
-i
在其他一些 sed 中(至少GNU和 Busybox),该-i
选项需要选修的后缀的参数,这样在同一命令行参数字符串中它后面的任何内容都是后缀。它通常以-i[suffix]
文档形式呈现。您可以-i.suffix
在 shell 中编写,或者只是-i
不给出后缀。在这些中-iE
仍然会产生E
后缀,但-i -E
可以作为两个选项。
在这两种情况下,-iE
都表示使用后缀E
,而在 FreeBSD/Mac 中,则-Ei ...
采用以下参数作为后缀(您将 sed 程序放在问题中的后缀)。
如果您想为没有备份文件提供空后缀,那么这两种方法是不兼容的。在这种情况下,您必须了解其区别并-i "" -E
与 FreeBSD/Mac 或-i -E
GNU 一起使用。
或者,如果您想要备份文件或不关心,则可以使用-i.bak -E
其中任何一个。 (您可以稍后删除备份文件。)
答案3
-iE
表示使用扩展名备份文件"E"
。你必须使用:
sed -i.old -E ...
将文件备份filename
到filename.old
.
在阅读评论和您的环境 (macOS) 的更新后,我添加了几个链接,您可以在其中找到有关sed
使用的有用信息-i
:
另外,如果您想替换版本,可能使用以下命令更具可读性awk
:
awk -v v='1.24.0.2' '
/PACKAGE_VERSION/{gsub(/[0-9]+(\.[0-9]+){3}/,v)}1
' force-app/main/default/classes/Constants.cls > file.tmp &&
mv file.tmp force-app/main/default/classes/Constants.cls
注意:您不能使用输入文件作为目标,因为它会被截断,这就是您在帖子末尾提到的内容。临时文件用于提供帮助。
一般来说,在使用awk
或时,我更喜欢使用临时文件,而sed
不是它们的就地选项(对于 GNU awk
)。上述命令预计适用于您的两种环境。
答案4
您可以按如下方式执行此操作。对于 macOS,该变量设置为非空值;对于其他系统,该变量设置为空值。然后,如果是 macOS,shell 扩展将扩展为带引号的空值,否则不会扩展(Linux 机器)
os=$(case $(uname) in Darwin*) echo x;; esac)
sed -Ei ${os:+""} -e "..." file