这篇文章以sed的一个参数的使用示例进行说明在不同操作系统之下,一些常用的命令或者操作系统内置的功能可能会有所不同,是脚本编程在实际编码中需要额外注意的事情。
示例说明
比如希望把如下文本文件中的GREETING_MSG使用sed替换成liu miao
[root@liumiaocn ~]# cat test.text
hello GREETING_MSG to use bash
[root@liumiaocn ~]#
示例代码
[root@liumiaocn ~]# cat test.sh
#!/bin/bash
FILE_TXT=test.text
WORDS_REPLACE_SRC="GREETING_MSG"
WORDS_REPLACE_DST="liu miao"
if [ ! -f ${FILE_TXT} ]; then
echo "File $FILE_TXT does not exist"
exit 1
fi
echo "Before sed -i "
cat $FILE_TXT
echo
sed -i s@"${WORDS_REPLACE_SRC}"@"${WORDS_REPLACE_DST}"@g $FILE_TXT
echo "After sed -i "
cat $FILE_TXT
[root@liumiaocn ~]#
CentOS 7.7下的执行结果
[root@liumiaocn ~]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
[root@liumiaocn ~]# sh test.sh
Before sed -i
hello GREETING_MSG to use bash
After sed -i
hello liu miao to use bash
[root@liumiaocn ~]#
macOS下的执行结果
同样的代码和准备在macOS下的执行结果如下所示:
liumiaocn:~ liumiao$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.2
BuildVersion: 19C57
liumiaocn:~ liumiao$
liumiaocn:~ liumiao$ cat test.text
hello GREETING_MSG to use bash
liumiaocn:~ liumiao$ sh test.sh
Before sed -i
hello GREETING_MSG to use bash
sed: 1: "test.text": undefined label 'est.text'
After sed -i
hello GREETING_MSG to use bash
liumiaocn:~ liumiao$
可以看到sed执行出错,这是因为在macOS上的sed在使用-i参数的时候需要额外指定一个标签用于备份源文件,设定为空就不会备份,将代码做如下修改即可:
liumiaocn:~ liumiao$ cp test.sh test.sh.org
liumiaocn:~ liumiao$ vi test.sh
liumiaocn:~ liumiao$ diff test.sh test.sh.org
16c16
< sed -i "" s@"${WORDS_REPLACE_SRC}"@"${WORDS_REPLACE_DST}"@g $FILE_TXT
---
> sed -i s@"${WORDS_REPLACE_SRC}"@"${WORDS_REPLACE_DST}"@g $FILE_TXT
liumiaocn:~ liumiao$
再次执行就会成功
liumiaocn:~ liumiao$ sh test.sh
Before sed -i
hello GREETING_MSG to use bash
After sed -i
hello liu miao to use bash
liumiaocn:~ liumiao$
总结
通过sed的-i参数在不同平台上的执行方式不同,如果需要在多个平台上进行兼容的情况下,或者将代码进行移植的情况下,都需要考虑,最好的方式当然还是使用POSIX的规范之内的部分,此部分之外的情况则需要多多考虑,很多常用的命令在不同平台下的表现可能会相差较大,这部分情况有时使用GNU版本的功能也是一个经常性的选择。