3.2 sed

3.2.1 正则表达式

基本正则表达式

  • .,表示匹配任意一个字符,除了换行符,类似 Shell 通配符中的 ?;

  • *,表示前边字符有 0 个或多个;

  • .*,表示任意一个字符有 0 个或多个,也就是能匹配任意的字符;

  • ^,表示行首,也就是每一行的开始位置,^abc 匹配以 abc 开头的字符串;

  • $,表示行尾,也就是每一行的结尾位置,}$ 匹配以大括号结尾的字符串;

  • {},表示前边字符的数量范围,{2},表示重复 2 次,{2,}重复至少 2 次,{2,4} 重复 2-4 次;

  • [],括号中可以包含表示字符集的表达式

(二)扩展正则表达式

扩展正则表达式使用频率上没有基本表达式那么高,但依然很重要,很多情况下没有扩展正则是搞不定的,sed 命令使用扩展正则时需要加上选项 -r。

  • ?:表示前置字符有 0 个或 1 个;

  • +:表示前置字符有 1 个或多个;

  • |:表示匹配其中的一项即可;

  • ():表示分组,(a|b)b 表示可以匹配 ab 或 bb 子串,且命令表达式中可以通过 \1、\2 来表示匹配的变量

  • {}:和基本正则中的大括号中意义相同,只不过使用时不用加转义符号;

3.2.2 语法

sed [option] 'command' filename

command

command 子命令格式:

[地址1, 地址2] [函数] [参数(标记)]

基本子命令

  1. 替换子命令 s

    # 将每行的hello替换为HELLO,只替换匹配到的第一个
    $ sed 's/hello/HELLO/' file.txt
    
    # 将匹配到的hello全部替换为HELLO,g表示替换一行所有匹配到的
    $ sed 's/hello/HELLO/g' file.txt
    
    # 将第2次匹配到的hello替换
    $ sed 's/hello/A/2' file.txt
    
    # 将第2次后匹配到的所有都替换
    $ sed 's/hello/A/2g' file.txt
    
    # 在行首加#号
    $ sed 's/^/#/g' file.txt
    
    # 在行尾加东西
    $ sed 's/$/xxx/g' file.txt
    
    • 多个匹配
    # 将1-3行的my替换为your,且3行以后的This替换为That
    $ sed '1,3s/my/your/g; 3,$s/This/That/g' my.txt
    
    # 等价于
    $ sed -e '1,3s/my/your/g' -e '3,$s/This/That/g' my.txt
    
  2. 追加子命令 a

     # 将所有行下边都添加一行内容A
     $ sed 'a A' file.txt
    
     # 将文件中1-2行下边都添加一行内容A
     $ sed '1,2a A' file.txt
    
  3. 插入子命令 i

  4. 替换子命令 c

  5. 删除子命令 d

option

  • -n,表示安静模式。默认 sed 会把每行内容处理完毕后打印到屏幕上,加上选项后就不会输出到屏幕上。

  • -e,如果需要用 sed 对文本内容进行多种操作,则需要执行多条子命令来进行操作;

  • -i,默认 sed 只会处理模式空间的副本内容,不会直接修改文件,如果需要修改文件,就要指定 -i 选项;

  • -f,如果命令操作比较多时,用 -e 会有点力不从心,这时需要把多个子命令写入脚本文件,使用 -f 选项指定执行该脚本;

  • -r:如果需要支持扩展正则表达式,那么需要添加 -r 选项;

3.2.3 数字定址和正则定址

数字定址

# 只将第4行中hello替换为A
$ sed '4s/hello/A/g' file.txt
# 将第2-4行中hello替换为A
$ sed '2,4s/hello/A/g' file.txt
# 从第2行开始,往下数4行,也就是2-6行
$ sed '2,+4s/hello/A/g' file.txt
# 将最后1行中hello替换为A
$ sed '$s/hello/A/g' file.txt
# 除了第1行,其它行将hello替换为A
$ sed '1!s/hello/A/g' file.txt

正则定址

# 将匹配到hello的行执行删除操作,d 表示删除
$ sed '/hello/d' file.txt
# 删除空行,"^$" 表示空行
$ sed '/^$/d' file.txt
# 将匹配到以ts开头的行到以te开头的行之间所有行进行删除
$ sed '/^ts/,/^te/d' file.txt