写在前面
本篇是个人学习整理笔记而得。
原书:Sed and Awk 101 Hacks -中文版
引用书结尾的一句话:
Knowledge is not one man’s Entity
sed 附加命令
1. sed 附加命令
### 语法
sed '[address] a the-line-to-append' input-file
### 在指定行后添加一行,第2行后添加一行203
sed '2 a 203,Jack,Engineer' employee.txt
### 在匹配行后添加多行
sed '/Jason/a 203,Jack Johnson,Engineer\n204,Mark Smith,Sales Engineer' employee.txt
2. 插入 i 命令
### 语法
sed '[address] i the-line-to-insert' input-file
### 在指定行前插入一行,在第2行之前添加一行203
sed '2 i 203,Jack,Engineer' employee.txt
### 插入多行,用法同上
3. 修改 c 命令
### 语法
sed '[address] c the-line-to-insert' input-file
### 用新行取代旧行,可以与 s 命令等价使用
sed '2 c 202,Jack,Engineer' employee.txt
sed '2s/.*/202,Jack,Engineer/' employee.txt
### 可以用多行取代一行,用法同上
4. 打印不可见字符 l 命令
sed -n 'l' dos.txt
### l 命令后指定数字,会在第n个字符使用一个不可见的自动折行
sed -n 'l 20' employee.txt
5. 打印行号 = 命令
### 打印所有行的行号
sed '=' employee.txt
### 打印指定行的行号
sed '1,3=' employee.txt
### 打印匹配到行的行号
sed '/Jane/=' employee.txt
### 配合-n,打印总行数(最后一行的行号)
sed -n '$=' employee.txt
6. 转换字符 y 命令
### 命令y可以根据对应位置转换字符
# 常用于,大小写转换
sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' employee.txt
7. 操作多个文件
sed -n '/root/p' /etc/passwd /etc/group
8. sed退出 q 命令
### 在指定行,退出
sed '3 q' employee.txt
### 匹配到行,退出
sed '/Manager/q' employee.txt
9. 读取文件数据 r 命令
### r命令会读取另一个文件的内容,并在指定的位置打印出来# 在指定到的行,打印另一个文件内容
sed '$r log.txt' employee.txt
### 在匹配到的行,打印另一个文件的内容
sed '/Raj/r log.txt' employee.txt
10. 选项 和 命令
### -l选项用于指定行的长度(需要配合l命令使用)
sed -nl 20 'l' employee.txt
### l命令也可以单独使用指定行长度
sed -n 'l20' employee.txt
### 容易混淆的还有
# -i 选项,直接修改原文件 <> i命令用于插入数据
# -n 选项,屏蔽默认输出 <> n命令打印模式空间
sed 保持空间和模式空间
1. 概念
sed 有两个内置的存储空间:
- 模式空间:
如你所知,模式空间用于 sed 执行的正常流程中。该空间 sed 内置的一个缓冲区,用来存放、修改从输入文件读取的内容。- 保持空间:
保持空间是另外一个缓冲区,用来存放临时数据。sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。我们已经讨论过,每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容。则保持不变,不会在循环中被删除。
2. 交换 x 命令
命令x(exchange) 用于交换模式空间和保持空间的内容
3. 模式空间复制到保持空间 h命令
命令h(hold), 与x命令不同在于不会改变模式空间当前内容,保持空间的内容会被覆盖
( cat << EOF
John
Doe
CEO
Jason Smith
IT Manager
Raj Reddy
Sysadmin
Anand Ram
Developer
Jane Miller
Sales Manager
EOF
) > empname.txt
]# sed -n -e '/Manager/!h' -e'/Manager/{x;p}' empname.txt
Jason Smith
Jane Miller
######################################################################################
# 逐行的读取,'/Manager/!h'表示遇到不包含Manager关键字的行,就复制到保持空间(注意是覆盖了保
# 持空间原有的内容),'/Manager/{x;p}'表示遇到包含Manager关键字的一行,就与保持空间交换并打印
# 交换后的模式空间内容(打印内容就是上一行,也就是Manager的姓名)。
######################################################################################
4. 模式空间追加到保持空间 H命令
### 同时管理者姓名和职位
]# sed -n '/Manager/!h;/Manager/{H;x;p}' empname.txt
Jason Smith
IT Manager
Jane Miller
Sales Manager
#### 格式化为一行
]# sed -n '/Manager/!h;/Manager/{H;x;s/\n/: /p}' empname.txt
Jason Smith: IT Manager
Jane Miller: Sales Manager
5. 保持空间复制到模式空间 g命令
### 打印管理者的姓名
]# sed -n '/Manager/!h;/Manager/{g;p}' empname.txt
Jason Smith
Jane Miller
6. 保持空间追加到模式空间 G命令
### 格式打印管理者及其职位
]# sed -n '/Manager/!h;/Manager/{x;G;s/\n/: /p}' empname.txt
Jason Smith: IT Manager
Jane Miller: Sales Manager
]#
######################################################################################
# m代表模式空间,h表示保持空间
# 先交换(m中为姓名,h为职位),再h追加到m中(m中姓名和职位分行排列),最后替换换行符
######################################################################################
7. 读取下一行数据附加到模式空间 N命令
### n打印当前模式空间内容并清空,读取下一行到模式空间### N不打印不清空,读取下一行追加到模式空间
]# sed -n 'N;s/\n/: /p' empname.txt
John: Doe
CEO: Jason Smith
IT Manager: Raj Reddy
Sysadmin: Anand Ram
Developer: Jane Miller
8. 打印多行模式中的第一行 P命令
### p打印模式空间的内容### P打印模式空间的第一行
]# sed -n 'N;/Manager/P' empname.txt
Jason Smith
Jane Miller
]# sed -n 'N;/Manager/l' empname.txt
Jason Smith\nIT Manager$
Jane Miller\nSales Manager$
]#
######################################################################################
# 'N' 将下一行追加到当前行(相当于每两行合并成一行,来执行第二条命令,并没有删掉换行符),
# '/Manager/P' 会匹配是否包含Manager, 如果包含P打印至换行符'\n'(也就是管理者姓名)
######################################################################################
9. 删除多行模式中的第一行 D命令
- d 删除模式空间的内容,然后读取下一行到空间,并且忽略后边的命令,进行新一次的循环
- D 删除模式空间的第一行,不读取下一行,忽略后边的命令,在当前空间从头执行命令
10. 命令b 和 :label标签 和 t命令
### :label 定义一个标签### b label 会跳转到label标签执行其之后的命令# 格式打印,并在管理者前加*号
]# sed -n '{
> N;
> s/\n/: /
> /Manager/!b end
> s/^/*/
> :end
> p}' empname.txt
John: CEO
*Jason Smith: IT Manager
Raj Reddy: Sysadmin
Anand Ram: Developer
*Jane Miller: Sales Manager
]#
######################################################################################
# 这里定义了一个end标签,后边接了一个命令p
# 第三行匹配Manager关键字,不匹配的直接跳转到end标签之后
# 匹配的会先执行替换开头为*的操作,然后再执行后边的命令
# t label 如果前面命令执行成功,会跳转到 label标签往下执行后续命令### 否则,按正常流程执行
######################################################################################
]# sed -n '{
N;
s/\n/: /;
:repeat;
/Manager/s/^/*/
/\*\*\*/!t repeat
p }' empname.txt
John: CEO
***Jason Smith: IT Manager
Raj Reddy: Sysadmin
Anand Ram: Developer
***Jane Miller: Sales Manager
]#
######################################################################################
# 定义了一个repeat标签
# /Manager/s/^/*/ 是循环块,给包含Manager行前加*号# /\*\*\*/!t repeat 匹配是否包含三个*号的行,不包含跳转回repeat标签处# 包含了的话,往下执行
######################################################################################