这里记录一下sed的使用, 并不会总结得很全,只是一些常见使用方法。 推荐一篇很好的sed的总结性文章点击这里 (是英文的,可能需要翻墙)
sed的常用方法
1. 替换字符串
1. 例子1(简单替换)
echo 'caesar is king' | sed 's/caesar/pig/'
# 输出结果: pig is king
这是最简单的使用方式,其中caesar
作为被替换的字符串, pig
作为替换字符串。
2. 例子2(全局替换)
sed
是每一行,每一行的流式操作的。
echo -e 'caesar is king, caesar\ncaesar is a girl' | sed 's/caesar/pig/'
# 输出结果: pig is king, caesar
# pig is a girl
可以看到sed
只是把每一行的第一个caesar
替换了, 不会替换所有的caesar
, 替换每一行的所有caesar
,需要加g
选项
echo -e 'caesar is king, caesar\ncaesar is a girl' | sed 's/caesar/pig/g'
# 输出结果: pig is king, pig
# pig is a girl
tip:
echo
的-e
选项是输出字符串会经过转义,\n
表示到下一行(linux)
3. 例子3(正则替换)
当然这里字符串的替换是可以使用正则表达式的, 一个例子如下:
echo -e 'caesar is king\ncurrent' | sed 's/^c[a-z]*/pig/'
# 输出结果: pig is king
# pig
这里将以c
开头的单词替换为pig
再来一个复杂的例子,比如用shell脚本进行代码的混淆时, 我想找到objective-c代码的方法,比如我的方法是这样的格式的
- (instancetype)mc_initWithTitle:(NSString *)title{
}
而我想要提取出mc_initWithTitle
这个方法名;
echo -e '- (void)mc_initWebView:(Nstring)3\n+ (void)mc_init;' | sed -r 's/^[-+] \(.*\)(mc_[0-9a-zA-Z_]*)([\;\:].*)?/\1/'
# 输出结果: mc_initWebView
# mc_init
这里-r
选项是--regexp-extended
,也就是正则扩展的意思, 不然sed的正则是不会识别()+
这些符号的,这里一步步解释:
1:^[+-]
代表以+
或者-
号开头;
2:空格就原样填写就行;
3:\(.*\)
表示匹配任何单词加圆括号的东西,如(void)
, (unsigned)
;
4:(mc_[0-9a-zA-Z_]*)
就是匹配方法名了;
5:([\;\:].*)?
表示各种方法后的符号, 有: 有; 也可以什么都没有;
6:\1
表示将之前匹配项1, 也就是(mc_[0-9a-zA-Z_]*)
作为替换项进行替换
我们就得到了我们的方法名了;
4. 不使用/作为分隔符
也可以不使用/
作为分隔符
sed 's_/usr/local/bin_/common/bin_' <old >new
sed 's:/usr/local/bin:/common/bin:' <old >new
sed 's|/usr/local/bin|/common/bin|' <old >new
这里改用_ : |
这三符号也行, 这样的话就可以不转义/
就可以识别/
了
5. &的使用
echo "123 abc" | sed 's/[0-9]*/& &/'
# 输出:123 123 abc
&
作为匹配项;
echo "123 abc" | sed 's/[^ ]*/(&)/g'
# 输出:(123) (abc)
给单词加上括号
6. /1 /2匹配第一个、匹配第二个
echo "abc def" | sed -r 's/[a-z]+/000/1'
# 输出: 000 def
echo "abc def" | sed -r 's/[a-z]+/000/2'
# 输出: abc 000
echo "abc def ghi" | sed -r 's/[a-z]+/000/2g'
# 输出: abc 000 000
2g
代表从第二个开始
2.其他操作
1. /p 打印
默认sed会打印所有行, 添加-n
参数,sed之后打印改变行
echo -e "abc def ghi\n12" | sed -n 's/abc/&/p'
# 输出:abc def ghi
这是使用sed
实现了grep
的操作
2. /p 打印指定行
echo -e "line1\nline2\nline3" | sed -n '1p'
# 输出:line1
echo -e "line1\nline2\nline3" | sed -n '1,2p'
# 输出:line1
# line2
echo -e "line1\nline2\nline3" | sed -n '$p'
# 输出:line3
# $p是打印最后一行
2. /I 忽略大小写
echo -e "abc\nABC" | sed -n '/abc/I p'
# 输出:abc
# ABC
3. 组合操作
echo -e "abca" | sed -n 's/a/A/2pw /tmp/file'
# 输出:abcA
# 并写入到/tmp/file tip:w要放在最后
4. -e多命令组合
echo -e "abc" | sed -e 's/a/A/' -e 's/b/B/'
# 输出:ABc
5. 多文件
sed 's/^#.*//' file1 file2 file3 | grep -v '^$' | wc -l
# 输出:输出多个文件中不是以#开头的行的行数
还有一个普遍使用方法是
sed 's/^#.*//' `grep -lr "pattern" dir`
# grep -lr dir输出文件夹dir下匹配pattern的文件
先写到这吧
todo: 写label g&G、 h&H、 x、 b、{}、