今天就看了这么一句代码:
opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"
看到晚上才看懂!真是弱爆了!
看nginx代码的configure脚本
./ auto/options
其中有一个for循环是
for option
do
opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"
case "$option" in
-*=*) value=`echo "$option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
.....#后续代码省略了
done
第一个for循环就弄的不明白。
原来shell中for循环后面不接in xxx 则代表for option in $@
而$@表示命令行参数组成的数组
所以其完整形式应该是
for option in $@
do
#循环代码省略
done
后面的opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"这句话楞是让我看了一天,顺便复习了一下sed,awk和正则表达是才明白。
下面以具体的例子说明一下这行代码的含义
如果执行./confiure --help=yes
那么for循环第一次进入时
$option的值为--help=yes
sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"这句话以一个正则表达式匹配$option中的值
去掉转移字符\后的正则表达式为(--[^=]*=)(.* .*)
这个正则表达式匹配的是如下的形式:--help=“aaaaa bbbb"
第一个()中匹配:--跟着任意长度的字符但不能是=,再跟着一个=
第二个()中匹配:任意字符+空格+任意字符
后sed后面的\1 与\2这表示第一个()所匹配的字符串和第2个()所匹配的字符串
简单点说就是第一个()中匹配--help=第2个()匹配”aaaa bbbb“
如果不懂正则表达式也能猜个大概是要分别匹配--help= 和这个选项的值。
但是opt的值又是什么呢?
这个就要对sed有所了解了。
这句代码中的模式是这样的:sed -e ”s/正则表达式/expression/“
如果内容与正则表达式匹配上,则sed输出expression替换正则表达式后这行的内容。
例如--help=”aaaa bbbb“就与正则表达式相匹配,所以$opt=--help='aaaa bbbb'
如果内容与正则表达式匹配不上,则sed会输出未匹配的这行内容。
例如--help=aaa 没有与正则表达式相匹配,sed输出未匹配的这行内容,所以opt=--help=aaa
这行代码的意思就是想匹配命令行中的选项,其中选项的格式如--help=”aaa bbb“
就是选项后的值可以用”引起来,并且可以包含空格。
但是平时我们最常用的格式是--help=yes,后面的值不需要用引号引起来,其中的值也就不能包含空格了。
opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"
这行代码既解决了选项中值有空格的问题,又能解决没有空格的问题。厉害!
总结
sed 后面的正则表达式若匹配则用expression替换正则表达式的值,并输出替换后的一行;
sed后面的正则表达式过不匹配则输出原始输入的那一行。
平时还用sed呢,看来对sed的认识真的不够深刻啊。
参考文献:
《sed与awk(第二版)》第2章 第3章 第4章 第5章P96
《Shell脚本学习指南》第六章 P154