余苏明的幻想乡

Chapter2 Sed Substitute 代替 Command

Chapter 2. Sed Substitute(代替) Command

6. Sed Substitute Command Syntax

1
2
3
sed '[address-range|pattern-range] s/originalstring/replacement-string/[substitute-flags]' inputfile
#sed '[地址范围|模板范围] s/原始字符串/替换字符串/[替换flag]' 输入文件
  • 地址范围或者模板范围是可选的。如果你没有选择这个选项, sed将会在所有行执行替换命令
  • s – 告诉sed执行替换命令
  • original-string –原始字符串将会在输入文件中搜寻。 原始字符串也能够是正则表达式
  • replacement-string – Sed 将会用这个字符串替换原始字符串
  • substitute-flags是可选的。 它可以包含以下一个或者多个值

源文件不会被修改

Replace all occurrences of Manager with Director:

1
2
3
4
5
6
$ sed 's/Manager/Director/' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Director
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Director

Replace Manager with Director only on lines that contain the keyword ‘Sales’:

根据关键字行替换。只在匹配到关键字的行替换

1
2
3
4
5
6
$ sed '/Sales/s/Manager/Director/' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Director

7. Global Flag (g flag)

全局flag:
sed默认替换模式是只替换每一行第一个匹配到的原始字符串。
如果你需要替换每一个字符串,则需要加上全局标志:g flag
1471403501349.png

Note:因为没有指定范围,所以这些实例将应用到整个文件中。

8. Number Flag (1,2,3.. flag)

使用数字Flag,将指定替换匹配到的每行的特定第n个原始字符串。
Counting starts over on each line, and n can be anything from 1 to 512.
从每行开始计数到结束,n能够取1-512范围(实测,到4096也没问题,之后没测。估计旧版本是到512)

1
2
sed 's/2/3/4096' 1|grep -o 3
3

Note: 如果单行没有指定多个匹配字符串,则这行nothing is changed

9. Print Flag (p flag)

p flag输出替换成功的行。和大部分p参数一样,联合-n参数一起使用,禁止默认输出所有行

1
$ sed -n 's/John/Johnny/p' employee.txt 101,Johnny Doe,CEO
1
2
3
4
5
6
7
[root@localordb 1]# sed -n 's/7/3/p' 1
3777
[root@localordb 1]# sed 's/7/3/p' 1
1
6
3777
3777

10. Write Flag (w flag)

将替换成功的行写入文件。等价于p参数+重定向>(不是>>)。大多数人都是使用p输出再重定向到文件。
所以这个参数不常用。而且不能输出到源文件

11. Ignore Case Flag (i flag)

忽略大小写。匹配时忽略原字符串的大小写。

12. Execute Flag (e flag)

执行命令flag,你可以执行任何一个有效的shell命令,将匹配到的源字符串当作命令参数,并输出结果。只有GNU的sed命令支持e flag

1
2
3
$ cat files.txt
/etc/passwd
/etc/group

1
2
3
$ sed 's/^/ls -l /e' files.txt
-rw-r--r-- 1 root root 1547 Oct 27 08:11 /etc/passwd
-rw-r--r-- 1 root root 651 Oct 27 08:11 /etc/group

13. Combine Sed Substitution Flags

你可以将多个Flag组合使用

14. Sed Substitution Delimiter

你可以更改定界符。
如果替换字符串中有/,再使用/定界符时要加转义字符\,这样很丑,而且不易读
所以sed支持使用其他符号作为定界符,以达到易读的效果。

1
2
$ sed 's/\/usr\/local\/bin/\/usr\/bin/' path.txt
reading /usr/bin directory

1
2
3
4
sed 's|/usr/local/bin|/usr/bin|' path.txt
sed 's^/usr/local/bin^/usr/bin^' path.txt
sed 's@/usr/local/bin@/usr/bin@' path.txt
sed 's!/usr/local/bin!/usr/bin!' path.txt

15. Multiple Substitute Commands Affecting the Same Line

sed命令可以对同一行执行多个sed替换命令
执行命令1之后,再执行命令2,知道执行完成,读取下一行。

Change Developer to IT Manager, then change Manager to Director:

1
2
3
4
5
6
7
8
9
10
$ sed '{
> s/Developer/IT Manager/
> s/Manager/Director/
> }' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Director
103,Raj Reddy,Sysadmin
104,Anand Ram,IT Director
105,Jane Miller,Sales Director

可以看到,第四行执行了两次替换命令

1.Read:

1
104,Anand Ram,Developer

2. Execute:

先执行了第一个替换命令s/Developer/IT Manager/

1
104,Anand Ram,IT Manager

然后执行了第二个替换命令s/Manager/Director/

1
104,Anand Ram,IT Director

Remember:第二个命令是在第一个命令执行完成的基础上执行的

3. Print:

执行完成所有的命令之后,输出结果

1
104,Anand Ram,IT Director

4. Repeat:

读取下一行,接着从step #1执行

更换两个命令顺序,结果不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sed '{
> s/Manager/Director/
> s/Developer/IT Manager/
> }' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Director
103,Raj Reddy,Sysadmin
104,Anand Ram,IT Manager
105,Jane Miller,Sales Director
#############################
cat employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

16. Power of & - Get Matched Pattern

&被使用在替换字符串中时,它将匹配任何源字符串或者正则表达式。这是非常强大并实用的

###

1
2
3
4
5
6
7
$ sed 's/^[0-9][0-9][0-9]/[&]/g' employee.txt
[101],John Doe,CEO
[102],Jason Smith,IT Manager
[103],Raj Reddy,Sysadmin
[104],Anand Ram,Developer
[105],Jane Miller,Sales Manager

17. Substitution Grouping (Single Group)

使用\(\)来确定分组,然后使用反向引用(e.g.\1 - \9)来引用分组

Single grouping:

1
2
3
4
5
6
7
$ sed 's/\([^,]*\).*/\1/g' employee.txt
101
102
103
104
105

encloses the 1st letter in every word inside (), if the 1st character is upper case.

1
2
3
# echo "The Geek Stuff Hello world" | sed 's/\(\b[A-Z]\)/\(\1\)/g'
(T)he (G)eek (S)tuff (H)ello world

18. Substitution Grouping (Multiple Group)

替换正则里有多个()的捕获分组,则可以用\1 - \9来反向引用

19. Gnu Sed Only Replacement String Flags

这些Flags只在GNU版本的sed命令才有效。这些Flags命令能用在替换字符串部分

\l ,\L,\u,\Ureplacement string flag

替换大小写,不管你替换字符串后面是大写还是小写,同意换成对应Flag的样式

  • \l为flag之后一个字符串为小写
  • \L为flag之后所有字符串全为小写
  • \u为flag之后一个字符串为大写
  • \U为flag之后所有字符串全为大写
    1
    2
    3
    4
    5
    $ sed -n 's/John/JO\lHNNY/p' employee.txt
    101,JOhNNY Doe,CEO
    #========================#
    $ sed -n 's/John/JO\LHNNY/p' employee.txt
    101,JOhnny Doe,CEO

\E replacement string flag

这个替换flag是联合\U,\L使用的,表示大小写替换的结束处

1
2
3
4
5
6
7
Change John to JOHNNY BOY:
$ sed -n 's/John/\UJohnny Boy/p' employee.txt
101,JOHNNY BOY Doe,CEO
#=========================#
Change John to JOHNNY Boy:
$ sed -n 's/John/\UJohnny\E Boy/p' employee.txt
101,JOHNNY Boy Doe,CEO

Replacement String Flag Usages

Employee name in all upper case, and title in all lower case:

1
2
3
4
5
6
7
$ sed 's/\([^,]*\),\([^,]*\),\(.*\).*/\U\2\E,\1,\L\3/g' employee.txt
JOHN DOE,101,ceo
JASON SMITH,102,it manager
RAJ REDDY,103,sysadmin
ANAND RAM,104,developer
JANE MILLER,105,sales manager