sed 处理替换字符中的特殊字符

时间:2023-01-30 15:29:35

今天编写shell程序时遇到了一个关于sed命令的问题。问题简化如下。

文本文件1.txt中包含字符串[:50]

~/Documents/books/linux/test$:cat 1.txt 
[:50]
愿意想将[:50]替换为[50:100],脚本如下:
~/Documents/books/linux/test$:cat test.sh #!/bin/basholdstr="[:50]"newstr="[50:100]"cat 1.txt | sed -n 's/$oldstr/$newstr/p'
运行./test.sh,结果没有输出
~/Documents/books/linux/test$:./test.sh ~/Documents/books/linux/test$:
于是,我上网查找问题原因,

1,如何在sed里使用变量的问题,发现原来是双引号和单引号引用的区别

单引号:shell处理命令时,对其中的内容不做任何处理。即此时是引号内的内容是sed命令所定义的格式。
双引号:shell处理命令时,要对其中的内容进行算术扩展。如果想让shell扩展后得到sed命令所要的格式
下面是个简单的例子

~/Documents/books/linux/test$:name=chen
~/Documents/books/linux/test$:echo '$name'    # $当作字符处理
$name
~/Documents/books/linux/test$:echo "$name"    # $作为特殊字符处理
chen
网上总结了四种方案

1.       eval sed 's/$a/$b/' filename

2.       sed "s/$a/$b/" filename

3.       sed 's/'$a'/'$b'/' filename

4.       sed s/$a/$b/ filename

于是我将脚本中sed中的单引号改为双引号。


#!/bin/bash
oldstr="[:50]"
newstr="[50:100]"

cat 1.txt | sed -n "s/$oldstr/$newstr/p"
但是输出的结果却跟预想的不一样。结果如下:
~/Documents/books/linux/test$:./test.sh [[50:100]50]


仔细一下,应该跟sed中的正则表达式有关:

正则表达式认可的特殊字符有:

. * [ ] ^ $ { } \ + ? | ( )

这些特殊字符中的一个作为文本字符,需要在特殊字符前添加反斜杠字符\ 来转义它。

得到之前的结果是因为sed中的正则表达式[:50]表示第一个匹配: , 5,0任一字符用[50:100]进行替换。字符串[:50]第一个匹配的是:,所以得到[[50:100]50].所以我将oldstr中的[]进行转义,并且在sed命令选项中加上g进行完全替换。


#!/bin/bash
oldstr="\[:50\]"
newstr="[50:100]"

cat 1.txt | sed -n "s/$oldstr/$newstr/g;p"
则得到我想要的结果:

~/Documents/books/linux/test$:./test.sh 
[50:100]
问题解决完毕。