linux工具-sed

1. 基本语法

1.1 sed名称由来

sed:Stream Editor, 文本流编辑.

1.2 入门例子

# 读取文件filename, 将每行(第一行到最后一行)做修改, 把abc替换为def.
#     -e   : sed选项, 表示sed的动作写在命令行(即单引号中的内容), 如果只是用单个-e, 则-e选项可以省略.
#     1, $ : address-range, sed-command只操作adress-range范围内的文本, 此处表示从第一行到最后一行. address-range可以省略, 表示处理整个文本.
#     s/abc/def/ : sed-command, 对文本做的操作, 此处表示把abc替换为def.
#     filename   : 待处理文件.
sed -e '1, $ s/abc/def/' filename

1.3 语法格式

#完整格式
sed [-hnv][-e<script>][-f<script_file>] [text_file]

#-e格式, sed动作写在命令行
#     [option] : sed选项.
#     [address-range | pattern-to-match]: 指定sed-command操作的文本范围.
#     sed-command : 对文本的操作.
sed [option] '[address-range | pattern-to-match] sed-command' filename

#-f格式, sed动作写在脚本文件sed_script_file
sed [option] -f sed_script_file filename

2. sed选项(option)

sed的主要option如下:

短选项 长选项 说明
-e<script> --expression=<script> sed动作写在命令行,不使用脚本
(直接在命令行模式上进行sed的动作编辑),
与-f选项相对应. 此为默认选项.
-f<script_file> --file=<script_file> sed动作写在一个脚本文件内,
例如:-f file.sed, 表示用file.sed来执行sed动作
-h --help 显示帮助
-n --quit
--silent
只打印模式匹配的行,
默认情况下sed会把文件中所有行都打印出来.
-r 支持扩展的正则表达式.
-i 直接修改文件内容,
默认情况下sed只修改输出到Terminal的内容.

-e选项可以使用多个, 以执行多个操作

# 下例用了两个-e选项, 第一个删除匹配o的行, 第二个, 把3~5行中的h替换为k.
# 注意: 这两个动作(删除行和替换文本)是同时进行的, 所以第二个替换涉及的3~5行, 是指filename文件中的3~5行, 而不是删除匹配o的行之后的文本内容中的3~5行.
sed -e '/o/ d' -e '3, 5 s/h/k/' filename

3. sed动作

格式:'[address-range | pattern-to-match] sed-command'

sed动作分两部分 作用
address-range或pattern-to-match 指定文件中的一系列文本行,可以是特定范围内的行,也可以是匹配某模式的行.
sed-command 对上述的文本行进行处理.

注意:

  1. sed动作要写在一对单引号中,防止被shell解释为其它命令.
  2. sed动作的两部分之间可以有空格,也可以没空格.
  3. address-range | pattern-to-match是可选的,如果不指定,默认是文件中的所有行.

3.1. address-range | pattern-to-match

作用:指定文件中的一系列文本行,默认为文本中的所有文本行.

格式:address-range可以通过行号指定,也可以通过/pattern/指定

addr-range or pattern 说明
m 处理第m行,m为行号, $表示最后一行
/pattern/ 处理匹配/pattern/的行
m, n 处理m到n范围内的所有行,m/n为行号,逗号两边可以加空格
/pattern1/, /pattern2/ 处理匹配/pattern1/和/pattern2/范围内的所有行
m, /pattern/ 处理第m行~匹配/pattern/范围内的所有行.
/pattern/, n 处理匹配/pattern/~第n行范围内的所有行.
m, n! 反向选择, 处理m~n行之外的行.

例子:

3.1.1 待处理文件内容:

$ cat a.txt # 文件内容  
line first  
line second  
line third  
line forth  
line fifth  
line sixth  
line seventh  

3.1.2 通过行号指定行

注意: $表示最后一行

$ sed -n '3 p' a.txt     # 打印第3行到Terminal  
line third
$ 
$ sed -n '3,5 p' a.txt   # 打印第3~5行到Terminal  
line third  
line forth  
line fifth  
$ 
$ sed -n '3, $ p' a.txt   # 打印第3~最后行到Terminal  
line third  
line forth  
line fifth
line sixth  
line seventh  

3.1.3 通过pattern指定行

$ sed -n '/ne third/,/ne fifth/ p' a.txt # 打印匹配 /ne th/和/ne fi/ 之间的行到Terminal  
line third  
line forth  
line fifth  
$  
$ sed -n '3,/ne fif/ p' a.txt   
line third  
line forth  
line fifth  
$ sed -n '/ne third/,5 p' a.txt  
line third  
line forth  
line fifth  

3.1.4 反选,指定3~5行之外的行.

$ sed -n '3,5! p' a.txt  # 打印第3~5行之外的行到Terminal  
line first  
line second  
line sixth  
line seventh  

3.1.5 如果第二个pattern没匹配到,则打印到文件结尾

$ sed -n '/ne third/,/xxxx/ p' a.txt # 如果第二个pattern没匹配到,则打印到文件结尾  
line third  
line forth  
line fifth  
line sixth  
line seventh  

3.1.6 如果第一个pattern没匹配到,则匹配结果为空

$ sed -n '/xxxx/,/ne fift/ p' a.txt # 如果第一个pattern没匹配到,则匹配结果为空  
$   

3.2. sed-command

作用:对文本行进行处理.

常用sed命令如下:

操作 命令 说明
打印 p 打印匹配行(通常和-n选项配合使用)
= 打印文件行号
新增 a\text 在定位到的 "每一行" "后面" 附加新行text
i\text 在定位到的 "每一行" "前面" 附加新行text
删除 d 删除定位到的行
替换 c\text 指定范围内的文本替换为text
s/pattern/text/ 将行内匹配pattern的内容替换为text
读写文件 w filename 将文本写到filename文件中,类似于输出重定向
r filename 从文件filename中读文本,类似于输入重定向
退出 q 第一个模式匹配后退出 或 立即退出
多个命令 {命令;命令…} 执行多个命令, 命令间使用分号分隔开.
... ... ...

例子:

3.2.1 待处理文件内容:

$ cat a.txt # 文件内容  
line first  
line second  
line third  
line forth  
line fifth  
line sixth  
line seventh  

3.2.2 使用p命令,打印文本

$ sed -n '/ne th/,/ne fi/ p' a.txt  
line third  
line forth  
line fifth  

3.2.3 使用=命令,打印行号

$ sed -n '/ne th/,/ne fi/ =' a.txt  
3  
4  
5  

3.2.4 使用a命令,在每个匹配行后面追加一行文本

# 注意下面命令没有使用-n选项, 所以默认打印所以行, 并在address-range中行后添加新行new
$ sed  '/ne th/,/ne fi/ a\new' a.txt  
line first  
line second  
line third  
new  
line forth  
new  
line fifth  
new  
line sixth  
line seventh  

3.2.5 使用i命令,在每个匹配行前面追加文本

$ sed  '/ne th/,/ne fi/ i\new' a.txt  
line first  
line second  
new  
line third  
new  
line forth  
new  
line fifth  
line sixth  
line seventh  

3.2.6 使用c命令,将匹配到的address-range行替换为新文本

注意: 不是每行替换一份,而是整个address-range替换为一份.

$ sed  '/ne th/,/ne fi/ c\new' a.txt  
line first  
line second  
new  
line sixth  
line seventh  

3.2.7 使用d命令,删除匹配的行

$ sed  '/ne th/,/ne fi/ d' a.txt  
line first  
line second  
line sixth  
line seventh  

3.2.8 使用s命令,替换匹配行内容的文本

$ sed  '/ne th/,/ne fi/ s/line/Number/' a.txt  
line first  
line second  
Number third  
Number forth  
Number fifth  
line sixth  
line seventh  

3.2.9 使用多个命令

# 找到匹配o的行, 把o替换为k, 并打印该行, 多个命令写在花括号中, 并以分号分隔, 中间可以加空格
$ sed -n '/o/ {s/o/k/; p}' a.txt
line secknd
line fkrth

3.2.10 使用q退出

# 找到匹配o的行, 把o替换为k, 并打印该行, 并退出, 
# 由于有q命令, 所以操作完第二行后就退出, 不在处理第四行(第四行也匹配o).
$ sed -n '/o/ {s/o/k/; p}' a.txt
line secknd

4. /pattern/支持的正则

4.1 元字符

字符 说明
. 任意字符(换行符除外)
\w 字母, 数字, 下划线, 汉字
\s 空白符
\d 数字
\b 单词边界(开始或结束)
^ 行首(当前字符串开始)
$ 行尾(当前字符串结尾)

举例

# 使用.\+, 表示任意字符重复1次或多次(注意, 表示+需要用\+, 表示*直接用*)
echo "execute fail" | sed -e '1, $ s#te.\+#te pass#' # execute pass

# 使用\s\+\w\+, 表示多个空白后面跟多个\w
echo "execute fail" | sed -e '1, $ s#te\s\+\w\+#te pass#' # execute pass

# 使用\b, 这样e\b会定位到execute最后的e, 而不会匹配开头和中间的e.
echo "execute fail" | sed -e '1, $ s#e\b.*#e pass#' # execute pass

4.2 重复(量词)

量词 说明 注意
* 重复0次或更多次
+ 重复1次或更多次 注意要使用\+
? 重复0次或重复1次 注意要使用\?
{m} 重复m次 注意要使用\{m\}
{m,} 重复m次或更多次 注意要使用\{m, \}
{m,n} 重复m次到n次 注意要使用\{m, n\}

非贪婪匹配(懒惰匹配), 不过看起来sed中的非贪婪匹配不好使.
a\w*?b, 以a开头, 以b结束的字符串.
对于字符串aabab,
如果用a\w+b, +会匹配尽可能多的字符, 所以会匹配到aabab.
如果用a\w+?b, +?会匹配尽可能多的字符, 所以会匹配到aab.

4.3 字符转义

查找大部分元字符本身或量词本身等特殊字符时, 需要转义, 比如:

\.  \*  \\ 等, 表示本身时需要转义, 表示特殊意义时不需要转义.

但, 表示有一些特殊字符本身不需要转义:

+  (  )  {  } 等, 表示本身时不需要转义, 表示特殊意义时需要转义.

4.4 自定义字符集

在方括号中写一系列字符, 表示匹配这些字符中的任意一个:

举例 说明
[aeiou] 任意元音字母
[0-9] 任意数字, -表示范围
[_0-9a-zA-Z] 等价于\w

举例

# 使用字符集, 中括号不需要转义
echo "execute fail" | sed -e '1, $ s#e\b\s*[a-z]\+#e pass#' # execute pass

4.5 分支与分组

分支: \d{5}-\d{4}\|\d{5}, 中间的|表示"或", 匹配左边(五位数字-四位数字)或匹配右边(五位数字)都可以.
      注意, |需要转义, 使用\|
分组: \(\d{3}\.\){4}, 将一组字符(\d\d\d\.)重复4次.
      注意, ()需要转义, 使用\(\)

4.6 取反

代码 说明
\W 非\w的字符
\S 非\s的字符
\D 非\d的字符
\B 非\b的字符
[^x] 非x的字符
[^aeiou] 元音字符以外的字符

4.7 后向引用(向前引用)

# 向前引用, \1表示前面第一个圆括号中的内容.
echo "abc abc abc x" | sed -e '1, $ s#\(\w\+\) \1 \1#\1#'  # abc x

5. 在sed命令中进行变量替换

$ VAR="var0"
$ text="1234,abcd"
$ echo $text | sed 's/abcd/$VAR/' # 在单引号中变量替换不成功
1234,$VAR
$ echo $text | sed "s/abcd/$VAR/" # 在双引号中变量替换成功
1234,var0
$

待完成

posted @ 2020-09-10 11:37  编程驴子  阅读(137)  评论(0编辑  收藏  举报