本文目录:
1 sed中使用变量和变量替换的问题
2 反向引用失效问题
3 "-i"选项的文件保存问题
4 贪婪匹配问题
5 sed命令"a"和"N"的纠葛
1.sed中使用变量和变量替换的问题
在脚本中使用sed的时候,很可能需要在sed中引用shell变量,甚至想在sed命令行中使用变量替换。也许很多人都遇到过这个问题,但引号却死活调试不出正确的位置。其实这不是sed的问题,而是shell的特性。搞懂sed如何解决引号的问题,对理解shell引号问题有很大帮助,触类旁通,以后在使用awk、MySQL等等自带语法解析的工具时就不会再疑惑。
例如下面想输出a.txt的倒数5行的语句。可能顺手就写出了下面的命令行:
total=`wc -l
sed -n '$((total-4)),$p' a.txt
但很不幸,这会报错。一方面,"$"在sed中是特殊符号,放在定址表达式中时,它表示的是输入流的最后一行的标记。而$(())中也出现了"$"符号,这会让sed去解析该符号。另一方面,$(())这部分是使用shell计算而不是使用sed计算的,因此必须要将其暴露给shell,以便能让shell能解析它。
再说说shell中单引号、双引号和不加引号的情况。
单引号:单引号内的所有字符变为字面符号。但注意:单引号内不能再使用单引号,即使使用了反斜线转义也不允许。
双引号:双引号内的所有字符变为字面符号,但"\"、"$"、"`"(反引号)除外,如果开启了"!"引用历史命令时,则感叹号也除外。
不使用引号:几乎等同于使用了双引号,但会进行大括号和波浪号扩展。
上面关于双引号的情况,描述的并不是真正的完整,但已足够。这些只是它们的字面意义,引号真正的意义在于:决定命令行中哪些"单词"需要被shell解析,也决定哪些是字面意义不用被shell解析。
显然,单引号内所有字符都成为了字面符号,shell不会解析其内任何单词,例如单引号内变量不再被解析、命令替换和算术运算不再执行、不会进行路径扩展等等。总之,单引号内的字符全是普通字符,如果某些字符需要交给自带解析功能的命令解析,必须使用单引号。例如,"$"、"!"和"{}"在sed中均有特殊意义,要想让sed能解析它们,必须对它们使用单引号,否则必出错,或者产生歧义。例如下面3个sed语句中的符号都必须使用单引号才能得到正确结果。
sed '$d' filename
sed '1!d' filename
sed -n '2{p;q}' filename
而想要让特殊字符被shell解析,必须不能将其包