guoln 发表于 2012-1-14 11:49:04

bash shell - sed及awk文本捕获及替换

bash shell虽然支持正则表达式, 但是正则操作却不大给力.
看以下示例

case需求.
stream='background-image: url (a.jpg)asdfasdfasdf ;background:url(b.jpg);background'
需要将背景图片内容a.jpg及b.jpg后追加一个签名串.

sed替换不给力
如果用sed, 替换是不会有问题, 但是要在一句代码里进行捕获多个图, 将进行替换, 查阅了相关的sed文档, 貌似是需求处理不了.
代码示例
stream='background-image: url (a.jpg)asdfasdfasdf ;background:url(b.jpg);background'
echo $stream | sed 's#.*url *( *(.*) *).*#1#'

#输出b.jpg

awk代码块
用awk的话,(g)sub又没有sed里的匹配后的"后向引用"(即"1"). 但是可以有代码块可操作.
原理可利用awk里的函数match先用正则匹配url()里的内容, 再用substr将内容取出, 随之将流的位置置后.
循环操作.
代码如下:
stream='background-image: url (a.jpg)asdfasdfasdf ;background:url(b.jpg);background'

matches=$(echo $stream | awk 'BEGIN {ORS=" "} END {
gsub(/ */,"", $0)
input=$0
while (match(input, "url([^?;)]+)")) {
print substr(input, RSTART+4, RLENGTH-4)
input=substr(input, RSTART+RLENGTH)
}
}')

for bg_file in `echo "${matches}"`; do
md5_code="test"
stream=$(echo "${stream}" | sed "s#url *( *${bg_file} *)#url(${bg_file}?v=${md5_code})#")
done

echo "${stream}"

总结
从以上的示例可以看出, awk几乎可以替代sed, 但是对于固定替换, sed使用起来更方便.
sed从使用理解上看, 与vi的命令操作很相似.
而在awk里块里几乎可以操作任意文本流.
另外要说明的是, 这两个命令所支持的正则都像是标准perl里的子集, 没有贪婪匹配与非贪婪匹配之分.
其实你应该很意外, 我为什么不用python或者php这种语言来写, 如果用字符串函数比较多的语言来写的话, 应该是非常之简单.
很遗憾也很高兴的, 这次有点钻牛角尖, 依然用了bash.
也算为学bash打下个基础.
页: [1]
查看完整版本: bash shell - sed及awk文本捕获及替换