解决sed替换“路径”字符串的问题

版权声明:本文为博主原创文章,转载请注明出处,谢谢合作! https://blog.csdn.net/sch0120/article/details/80323904

问题描述

先来看出问题的脚本:

target=/dev/nvme1n1 # 实际为动态获得
sed -i "s/^filename=.*/filename=$target/" ./ebs_*.fio

脚本中用某种方法动态地获得了一个块设备,它是一个带有/的路径。接下来脚本需要将这个“块设备”配置到./ebs_*.fio这些配置文件中。

执行脚本时报错sed: -e expression #1, char 26: unknown option to 's',使用bash -x调试脚本发现sed命令所在行被解析为:

+ sed -i 's/^filename=.*/filename=/dev/nvme1n1/' ./ebs_ssd_randread.fio ./ebs_ssd_randwrite.fio

问题分析

我们知道sed可以用来替换文本文件中的指定字符串,它的一般语法如下:

sed 's/oldstring/newstring/' file

如果需要newstring中包含特殊字符需要用\进行转义。那么脚本中的sed语句应该写为:

sed -i 's/^filename=.*/filename=\/dev\/nvme1n1/' ./ebs_*.fio

但是,脚本用到的块设备是动态获取的,因此只能用变量去做替换:

sed -i "s/^filename=.*/filename=$target/" ./ebs_*.fio

我们不便对$target变量的内容(/dev/nvme1n1)进行转义,因此变量中的/就会与sed语句的语法冲突,从而产生错误。

解决办法

通过学习sed命令,我发现它有一个很好的设计,就是命令的语法非常灵活。当你不方便转义字符串中/的时候,sed命令支持自定义语法的分隔符,让你可以避开这个问题。

用户自定义语法的分隔符很简单,就是在s的后面紧跟自定义的分隔符即可,比如?等等……

$ cat file
aaaaaa
bbbbbb
cccccc
$ sed 's/bb/ee/' file
aaaaaa
eebbbb
cccccc
$ sed 's%bb%ee%' file
aaaaaa
eebbbb
cccccc
$ sed 's$bb$ee$' file
aaaaaa
eebbbb
cccccc
$ sed 's@bb@ee@' file
aaaaaa
eebbbb
cccccc
$ sed 's?bb?ee?' file
aaaaaa
eebbbb
cccccc
$ sed 's?bb?ee?g' file
aaaaaa
eeeeee
cccccc

因此,只要稍微变通一下,把脚本改为下面的样子,就可以顺利执行:

target=/dev/nvme1n1 # 实际为动态获得
sed -i "s?^filename=.*?filename=$target?" ./ebs_*.fio

另一种方法

上面的方法自然是最直接且简便的,还有一种比较容易想到的,可以算是一种“曲线救国”的方法:

target=/dev/nvme1n1 # 实际为动态获得
target_sed=$(echo $target |sed -e 's/\//\\\//g')
sed -i "s/^filename=.*/filename=${target_sed}/" ./ebs_*.fio

不再过多解释。

参考文献

  1. https://www.cnblogs.com/linux-wangkun/p/5745584.html
  2. https://blog.csdn.net/loveaborn/article/details/17269645

猜你喜欢

转载自blog.csdn.net/sch0120/article/details/80323904