linux中sed中用s 替换中遇到的问题
sed替换时候不能用-n,只输出替换的行,为什么????
比如:
sed "2,4s/\"//g" /var/lib/status #可以输出
但是:
sed -n "2,4s/\"//g" /var/lib/status #什么也数不出来了
问题:文件helloword,sh
root@ubuntu:/home/dyx/linux 17:25:36 188# nl -b a helloword.sh 1 #!/bin/bash 2 echo "helloword!"; 3 echo "The first parameter:" $1; 4 echo "The second parameter:" $2; 5 echo "The whole parameter is:" $@ 6 7 8 9 echo 'insert-------------------------------'; 10 echo '$0: '$0; 11 echo '$*: '$*; 12 echo '$@: '$@; 13 echo '$#: '$#; 14 echo '$!: '$!; 15 echo '$?: '$?; 16 echo '$$: '$$;
想把9到最后的行中单引号变为上引号;
用命令:
1 :sed '9,$s/\'/\"/g' helloword.sh
一直出现换行符号,不知道为什么,最后查了网上资料,说sed中用s替换最好用双引号“
于是查到:
1 sed "s/'/\"/g"
可以替换全部的,
之后用
1 sed "9,$s/'/\"/g"
就不可以了
1 root@ubuntu:/home/dyx/linux 17:32:18 189# sed "9,$s/'/\"/g" 2 sed: -e 表达式 #1, 字符 6: 未知的命令:“"”↵
发现需要在9和$之间留个空格,
1 root@ubuntu:/home/dyx/linux 17:33:33 191# sed "9,$ s/'/\"/g" helloword.sh 2 #!/bin/bash 3 echo "helloword!"; 4 echo "The first parameter:" $1; 5 echo "The second parameter:" $2; 6 echo "The whole parameter is:" $@ 7 8 9 10 echo "insert-------------------------------"; 11 echo "$0: "$0; 12 echo "$*: "$*; 13 echo "$@: "$@; 14 echo "$#: "$#; 15 echo "$!: "$!; 16 echo "$?: "$?; 17 echo "$$: "$$;
1 root@ubuntu:/home/dyx/linux 19:47:53 201# sed "8,$ s/\'/\"/g" helloword.sh 2 #!/bin/bash 3 echo "helloword!"; 4 echo "The first parameter:" $1; 5 echo "The second parameter:" $2; 6 echo "The whole parameter is:" $@ 7 8 9 " 10 echo 'insert-------------------------------';" 11 echo '$0: '$0;" 12 echo '$*: '$*;" 13 echo '$@: '$@;" 14 echo '$#: '$#;" 15 echo '$!: '$!;" 16 echo '$?: '$?;" 17 echo '$$: '$$;"
所以只有
1 sed "8,$ s/'/\"/g" helloword.sh
正确!
不太理解!
当用脚本时:
1 cat ss.sed 2 '6,$ s/'/"/g'
1 sed -f ss.sed helloword.sh
报错:
sed:文件 ss.sed 行号:1:未知的命令:“'”
sed -e "s/^'//g" -e "s/'$//g" ss.sed 6,$ s/'/"/g
这样就可以了。
但是
sed -e "/^'/d" -e "/'$/d" ss.sed
没反应?????
看过参考之后,发现sed中d是对整个行起作用的,所以就把那一行删掉了,当然没反应了啊
cat sssss.sed s#/#\#g
sed "s/\\\\/\\\\\\\\/g" sssss.sed s#/#\\#g
不知道你领悟没呢,其实在命令行中用sed的s代替,要转义两次,一次是终端的转义,一次是sed本身的转义;
参考一:
Sed使用的变量里含有转义字符的解决
最近写脚本的时候碰到了这方面的问题,到网上搜了半天也没找到好一点的方案或总结。今天我把自己的摸索写一下。
首先是Sed里使用变量的问题
网上有人总结了四种方案:
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后面的表达式一般用单引号引起来('),当需要使用变量时就换用双引号(")。
关于单双引号的区别:
单引号:shell处理命令时,对其中的内容不做任何处理。即此时是引号内的内容是sed命令所定义的格式。
双引号:shell处理命令时,要对其中的内容进行算术扩展。如果想让shell扩展后得到sed命令所要的格式,使用命令:sed -n "/\\\\$/p" haha,扩展后得到的结果即\\$.
因此对于语句类似:
$Comfilename="/home/evan/sandbox/Main/"
1. echo $Comfilename | sed 's#\/#\\\/#g'
2. echo $Comfilename | sed "s#\/#\\\/#g"
第一个的结果是:\/home\/evan\/sandbox\/Main\/
而第二个还是:/home/evan/sandbox/Main/ 因为双引号会将“\/“解释为”/“,所以sed "s#\/#\\\/#g"被Shell解释成了sed s#/#\/#g 到sed里执行时又把”\/“转义为”/“了,这样相当于进行了了两次解释,就得不到想要的结果了。
这个例子告诉我当没必要用双引号的的时候就不要用,要不然说不定什么时候你就会很郁闷。当然单引号效率要比双引号高也是不要滥用双引号的原因之一。
言归正传,如何在sed的变量里使用那些特殊的需要转义的字符呢?
网上提出的一种方法是将sed里表示替换用的s后面的表示分隔用的字符换成别的变量里没有的字符这样就相当于变量里没有要转义的字符了。
如:
sed –i "s# $Comfilename#/Root/#" filename.list
这是一个好办法。但很不幸我需要的是删除“d”不是替换“s“。当我把同样的方法用于删除时似乎没有起到作用:sed –i "# $Comfilename#d" filename.list
于是只能自己手工先改写变量
$Comfilename="/home/evan/sandbox/Main/"
Tempname=` echo $Comfilename | sed 's#\/#\\\/#g'` (这里把反单引号执行的结果给临时变量,同样的方法可以改写其他需要转义的符号。)
sed –i "# $ Tempname #d" filename.list
个人感觉这种方法不是很好,但在网上找了半天也没找到更好的方法,只能感叹SHELL的博大精深,吾辈还得慢慢求索。
参考二:
在使用sed对日志或者其它文本进行parse的过程当中,有时候我们需要引用外部变量的值,
或者获取一个shell命令执行的结果,以便达到更加可观的输出结果。这里介绍如何做到。
sed中使用变量替换
1.sed命令使用双引号的情况下,使用$var直接引用
$ echo|sed "s/^/$RANDOM.rmvb_/g"
29328.rmvb_
# 上面例子引用了一个环境变量$RANDOM的值
2.sed命令使用单引号的情况下,使用'"$var"'引用
类似,我们可以看到
$ echo|sed 's/^/'"$RANDOM"'.rmvb_/g'
31338.rmvb_
sed中执行外部命令
1.sed命令使用单引号的情况下使用'`shell command`'或者'$(shell command)'引用命令执行的结果
还是以上面案例分析,例子如下
$ echo|sed 's/^/'`echo $RANDOM`'.rmvb_/g'
8063.rmvb_
# 上面的例子使用了旧式的命令替换,也可以采用新式的命令替换方法,如下
$ echo|sed 's/^/'$(echo $RANDOM)'.rmvb_/g'
18554.rmvb_
# 下面例子取用当前日期作为结果的一部分,如下
$ echo|sed 's/^/'$(date +"%Y%m%d")'.rmvb_/g'
20120108.rmvb_
2.sed命令使用双引号的情况下直接`shell command`或者$(shell command)引用命令执行的结果
类似的,双引号的情况,如下
$ echo|sed "s/^/$(date +"%Y%m%d").rmvb_/g"
20120108.rmvb_
# 使用环境变量$RANDOM以及旧式命令替换的例子
$ echo|sed "s/^/`echo $RANDOM`.rmvb_/g"
4988.rmvb_
总结
在sed语句里面,变量替换或者执行shell命令,双引号比单引号少绕一些弯子