`
zealotds
  • 浏览: 119763 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

【摘译】Sed 简介 by Bruce Barnett

    博客分类:
  • bash
阅读更多
unix, sed, introduction, tutorial

原文:Sed - An Introduction and Tutorial by Bruce Barnett

#
# 基本使用方式:
#

1. 处理stdout或者stderr:
echo <something you want to print> | sed 's/<reg-pattern>/<replacement>/'

2. 处理文件:
sed 's/<reg-pattern>/<replacement>/' <old >new

s               substitute
<reg-pattern>   regular expression search pattern
<repalcement>   the replacing string you want to use
/               is the delimiter, seems every char except '&' following the 's' could be a delimiter

#
# 在<replacement>中使用 '&' 代替已匹配到的字符
#

sed 's/abc/(abc)/' <old >new
# 可以使用下边的语句替换s上边的语句
sed 's/abc/(&)/' <old >new

# '&'可以多次使用
# 注意这里[0-9]出现了两次,这是因为sed这类基本工具只能支持基本正则表达式
# 所谓基本正则表达式是不支持'+'这类修饰符的
# 目前貌似只有awk,nawk和egrep支持扩展正则表达式
echo "123 abc" | sed 's/[0-9][0-9]*/& &/'

#
# 使用\<num>s实现反向引用,这里的<num>可以是1~9的数字
#

echo abcd123 | sed 's/\([a-z\]*\).*/\1/'
# \([a-z]*\) 是一个t通过'\('和'\)'定义的组.可以通过\<num>反向引用已经匹配到的组

# 交换第一次和第二次匹配到的结果
sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/'
# 重复[a-z]以实现至少有一个字母匹配的效果
sed 's/\([a-z][a-z]*\) \([a-z][a-z]*\)/\2 \1/' 
# 反向引用表达式可以在<reg-pattern>和<replacement>中使用
# 下边这个表达式可以消除两个连续的以空格分隔的重复的词
sed 's/\([a-z]*\) \1/\1/' 
# 找出并显示连续的以空格相隔的词
# -n 会抑制打印pattern space(下边会有提到), 末尾的p用于显示当前(匹配?)的pattern space
# 具体信息可以参考man sed. 这里的pattern space概念不是很清晰,只找到了一篇文章有较多的提到
# 大致意思应该是待匹配的字符空间(串): http://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html
sed -n '/\([a-z][a-z]*\) \1/p' 
# 交换头三个字母的次序
sed 's/^\(.\)\(.\)\(.\)/\3\2\1/'

#
# 替换标识
#

# 所谓替换标识就是最有一个分隔符后边的那个字母,如上边例子里的p
# 替换标识用于控制当一行字符串中存在多个匹配点时下一步的具体行为

# /g 用于指示替换所有的匹配
# [^ ]中的^代表'非',这个表达式将匹配所有非空格的字符(就是一个英文单词)
# 然后用()包裹匹配到的单词并输出
sed 's/[^ ][^ ]*/(&)/g'
# /<num>用于指示要替换的匹配(的序号),num可以是1~512的数字
# 下边的表达式后最后的/2表示要替换第二个匹配,而/2左边紧邻的/是替换表达式的开始分隔符
# 因为两个/之间没有字符,就表示用空串替换,就是删除的意思啦
sed 's/[a-zA-Z]* //2'

# 默认情况下sed会打印所有的待匹配行,如果该行发生了替换那么久打印替换后的行
# 如果你使用了-n参数,sed会关闭该自动打印功能。此时如果再使用/p标识就可以实现只打印
# 被修改行的(处理后的)效果
# 下边的例子将只显示发生PATTERN替换的行,其作用相当于grep
sed -n 's/PATTERN/&/p' file 

# /w 用于将结果输出到一个文件
# 将file中以偶数开头的行输出到一个叫even的文件
sed -n 's/^[0-9]*[02468] /&/w even' <file

# 替换标识可以像其他unix命令参数一样组合使用
sed -n 's/a/A/2pw /tmp/file' <old >new


#
# 其它
#

# -e参数可以让你同时使用多个表达式:
sed -e 's/a/A/' -e 's/b/B/' <old >new

# 如果有多个输入参数,那这些参数就应该是文件名:
# sed首先把#开头的行全部替换成空行
# grep -v '^$'过滤掉空行
# 最后Wc -l统计出所有非空行的总数
# OK,这就是一个简单的代码统计工具啦
sed 's/^#.*//' f1 f2 f3 | grep -v '^$' | wc -l 

# 行范围的限定,只替换1到100行的内容
sed '1,100 s/A/a/'

# !!!这个非常有用!!!
# 去除路径里的相对路径符'..'
# 这里的关键在于最前边的':1'和最后边的';t 1'
# :1标示了下边的脚本的Label为1,而后边的;t 1就是当之前的脚本发生替换后重新跳转
# 到label 1,知道没有替换发生。就是一个循环啦!
echo c:/mingw/lib/../lib/gcc/mingw32/4.5.2/../../../../mingw32/include | sed ':1;s,/[^/.][^/]*/\.\./,/,;t 1'
# 上边的例子中如果没有使用;t命令则只能去除第一个'/lib/../lib'
# 在mingw环境中有可能出现Windows路径分隔符'\',此时只要多加一级过滤就OK:
sed -e 's,\\,/,g' -e ':1;s,[/\][^/.][^/]*/\.\.[/\],/,;t 1'


更多的关于各命令的介绍强烈推荐这酷壳这一篇
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics