1 Linux三剑客(grep,sed,awk)
2
3 这三个命令可以和正则表达式结合在一起,功能十分强大!!掌握了这三个命令,那么基本就可以对linux文件进行所有操作了.
4
5 grep擅长查找,sed擅长进行取行和替换操作,awk擅长进行取列操作.
6
7 先说一下,正则表达式的基本模板(普通字符+元字符):
8
9 | 字符 | 描述 |
10 | ---------- | ------------------------------------------------------------ |
11 | [A-Z] | [A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。 |
12 | [xyz] | 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a' |
13 | [^xyz] | 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'、'l'、'i'、'n' |
14 | \D | 匹配一个非数字字符。等价于 [ ^0-9] |
15 | \d | 匹配一个数字字符。等价于 [0-9] |
16 | \r | 匹配一个回车符 |
17 | \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v] |
18 | \S | 匹配任何非空白字符 |
19 | \w | 匹配字母、数字、下划线。等价于 [A-Za-z0-9_] |
20 | \W | 匹配非字母、数字、下划线 |
21 | . | 匹配除换行符(\n、\r)之外的任何单个字符 |
22 | ^ | 匹配输入字符串的开始位置,要匹配 ^ 字符本身,请使用 \^ |
23 | $ | 匹配输入字符串的结尾位置,要匹配 $ 字符本身,请使用 \\$ |
24 | \b | 匹配单词边界 |
25 | \B | 匹配非单词边界 |
26 | ( ) | 标记一个子表达式的开始和结束位置,子表达式可以获取供以后使用 |
27 | * | 匹配0个或多个,贪婪匹配 |
28 | + | 匹配1个或多个,贪婪匹配 |
29 | ? | 匹配0个或1个,非贪婪匹配 |
30 | \| | 或的意思,多选一(x\|y,匹配x或y) |
31 | {n} | 匹配n次. |
32 | {n,} | 匹配至少n次. |
33 | {n,m} | 匹配至少n次,至多n次. |
34 | | |
35 | 修饰符 | 描述 |
36 | i | ignore,不区分大小写,将匹配设置为不区分大小写,搜索时不区分大小写 |
37 | g | global,全局匹配,查找所有匹配项 |
38 | m | multi line,多行匹配,使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾 |
39 | s | 默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n |
40
41
42
43 详细的正则表达式介绍,请移步: https://www.runoob.com/regexp/regexp-tutorial.html
44
45
46
47 一.grep命令:
48
49 grep [OPTIONS] PATTERN [FILE..]
50
51 - --color=auto 对匹配到的文字着色显示(现在已经自动显示为红色了)
52
53 - **-v 显示不被pattern匹配到的行**
54
55 - -i 忽略字符大小写
56
57 - **-n 显示匹配的行号**
58
59 - **-c 统计匹配的行数**
60
61 - -d 指定要查找的是目录
62
63 - **-w 只显示包含匹配字符串的行**
64
65 - **-o 仅显示匹配到的字符串**
66
67 - **-A 10 after 后10行日志**
68
69 - **-B 10 before 前10行日志**
70
71 - **-C 10 context 前后(上下文)各10行日志**
72
73 - -e 实现多个选项间的逻辑or关系
74
75 grep -e '小明' -e '小王' 过滤出包含'小王'和'小明'的信息
76
77 - **-E 支持正则表达式**
78
79 ```shell
80 #举栗子
81 #grep -e和 grep -E区别
82 #1.grep -e只能检索一个内容
83 grep -e '小明' -e '小王' filename
84
85 #2.grep -E可以传递多个内容,使用 | 来分割多个pattern,以此实现OR操作
86 grep -E '小明|小王' filename
87
88 #在filename文件中找出含有word的所有行并显示,-n显示行号
89 grep -n 'word' filename
90
91 #在filename文件中找到wall或者well所在的行并显示
92 grep 'w[ea]ll' filename
93
94 #在file_name文件中找到”非well”所在的所有行并显示
95 grep 'w[^e]ll' filename
96
97 #在file_name文件中找到以The开头的所有行并显示
98 grep '^The' filename
99
100 #在file_name文件中找到goo(任意字符)(任意字符)le的所有行并显示(即总共七个字符)
101 grep 'goo..le' filename
102
103 #在file_name文件中找到g , gg , ggg等的所有行并显示(*代表重复前一个字符0~~无穷多次)
104 grep 'g*g' filename
105
106 #在file_name文件中找到Tyy,Tyyy的所有行并显示(注意{}在 shell中有特殊含义,故需要转义)
107 grep 'Ty\{2,3\}' filename
108
109 #注意:grep可以使用grep –color=always 来使得所查找的字符拥有特殊颜色,然后在执行source ~/.bashrc 来使得设置立即生效
110
111 ```
112
113
114
115
116
117 ### 二.sed命令:
118
119 sed是一种流编辑器,**实现数据的替换,删除,增加,选取等(以行为单位进行处理),它一次处理一行内容**。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如‘D’ 的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。**文件内容并没有改变,除非你使用重定向存储输出**
120
121 #### sed [ -hnV ] [ -e< script>] [ -f< script文件>] [文本文件]
122
123 - -e 多点编辑,以选项中指定的script来处理输入的文本文件
124 - -f 以选项中指定的script文件来处理输入的文本文件
125 - -E/r 支持扩展正则表达式
126 - -n 只显示匹配处理的行(不加-n,则会输出所有)(也就是关闭默认的输出)
127 - **-i 编辑原文件!**
128 - **-i.bak 备份原文件并编辑原文件(不是备份的)**
129
130 文本编辑动作(在script中)
131
132 - a 新增,a后面新增的字符串会出现在**当前行的下一行**,支持使用\n实现多行追加.
133
134 - i 插入,i 的后面可以接字符串,会出现在当**前行的上一行**.
135
136 - = 显示行号
137
138 - p 打印当前模式空间内容, 通常 p 会与参数 sed -n 一起运行.
139
140 - c 替换,替换行为单行或多行文本.
141
142 - d 删除,删除模式空间匹配的行,并立即启用下一轮循环
143
144 - **s s///, 查找替换,支持使用其它分隔符,s@@@,s###**
145
146 替换标记:
147
148 - **g, 行内全局替换**
149 - p, 显示替换成功的行
150 - w, /path/to/somefile 将替换成功的行保存至文件中
151
152 ```shell
153 #举栗子
154 zx@xx:[/xx/xx]cat -n test.txt
155 1 admin
156 2 root
157 3 user admin
158 4 password
159 5 password
160
161 #在第二行前加ROOT
162 zx@xx:[/xx/xx]sed -e '2iROOT' test.txt| cat -n
163 1 admin
164 2 ROOT
165 3 root
166 4 user admin
167 5 password
168 6 password
169
170 #在第二行后加ROOT
171 zx@xx:[/xx/xx]sed -e '2aROOT' test.txt|sed =
172 1
173 admin
174 2
175 root
176 3
177 ROOT
178 4
179 user admin
180 5
181 password
182 6
183 password
184
185 #删除前2行
186 zx@xx:[/xx/xx]cat -n test.txt | sed -e '1,2d'
187 3 user admin
188 4 password
189 5 password
190
191 #从第三行开始删除到底
192 zx@xx:[/xx/xx]cat -n test.txt | sed -e '3,$d'
193 1 admin
194 2 root
195
196 #删除包含user的行
197 zx@xx:[/xx/xx]sed '/user/d' test.txt
198 admin
199 root
200 password
201 password
202
203 #插入2行数据
204 zx@xx:[/xx/xx]cat -n test.txt | sed -e '2ax\ny'
205 1 admin
206 2 root
207 x
208 y
209 3 user admin
210 4 password
211 5 password
212
213 #替换内容,2-3行替换
214 zx@xx:[/xx/xx]cat -n test.txt | sed -e '2,3c hello'
215 1 admin
216 hello
217 4 password
218 5 password
219
220 #重复打印1-2行
221 zx@xx:[/xx/xx]sed -e '1,2p' test.txt|cat -n
222 1 admin
223 2 admin
224 3 root
225 4 root
226 5 user admin
227 6 password
228 7 password
229
230 #打印1-3行
231 zx@xx:[/xx/xx]sed -n '1,3p' test.txt| nl
232 1 admin
233 2 root
234 3 user admin
235
236 #将password替换成pwd
237 zx@xx:[/xx/xx]sed -e 's/password/pwd/g' test.txt
238 admin
239 root
240 user admin
241 pwd
242 pwd
243
244 #先将password替换成pwd,再删除pwd
245 #-e 多点编辑
246 zx@xx:[/xx/xx]sed -e 's/password/pwd/g' -e '4,$d' test.txt
247 admin
248 root
249 user admin
250
251 #-i 直接修改原文件, -i.bak备份原文件
252 zx@xx:[/xx/xx]sed -i '1a hello' test.txt
253 zx@xx:[/xx/xx]cat -n test.txt
254 1 admin
255 2 hello
256 3 root
257 4 user admin
258 5 password
259 6 password
260 zx@xx:[/xx/xx]sed -i.bak '1i hello' test.txt
261 zx@xx:[/xx/xx]cat -n test.txt
262 1 hello
263 2 admin
264 3 hello
265 4 root
266 5 user admin
267 6 password
268 7 password
269 zx@xx:[/xx/xx]cat -n test.txt.bak
270 1 admin
271 2 hello
272 3 root
273 4 user admin
274 5 password
275 6 password
276
277 #懒,就不贴输出了-.-(以前的笔记)
278 #删除file_name文件的2到4行
279 sed '2,4d' filename
280
281 #在第二行下新增这样两行
282 sed '2a lv .....\
283 duidui is shuai!!!' filename
284
285 #把file_name文件的2到4行,替换为ni han ma a !!
286 sed '2,4c ni han ma a!!!' filename
287
288 #把file_name文件的2到5行打印出来(不用-n 参数,就会重复输出2到5行)
289 sed '2,5p' -n filename
290
291 #把file_name文件中的a[t]. 全部替换为p_temp-> (-i 会直接将修改写入文件,[ ] 和 . 是特殊符号,需要用\来转义一下)
292 sed -i 's/a\[t\]\.p_temp->/g' filename
293
294 #找出文件名(文件格式前的名字)
295 zx@xx:[/xx/xx]find *.txt
296 1.txt
297 2.txt
298 3.txt
299 zx@xx:[/xx/xx]find *.txt|sed -r 's/(.*).txt/ \1/'
300 1
301 2
302 3
303 zx@xx:[/xx/xx]find *.txt|sed -E 's/(.*).txt/ \1/'
304 1
305 2
306 3
307 #找出文件名之后,将其改名
308 #mv移动文件或改名, bash是执行mv命令
309 zx@xx:[/xx/xx]find *.txt|sed -E 's/(.*).txt/mv \1.txt \1.md/'
310 mv 1.txt 1.md
311 mv 2.txt 2.md
312 mv 3.txt 3.md
313 zx@xx:[/xx/xx]find *.txt|sed -E 's/(.*).txt/mv \1.txt \1.md/'|bash
314
315 ```
316
317
318
319 ### 三.awk命令:
320
321 awk 是一种处理文本文件的语言,是一个强大的文本分析工具.
322
323 #### awk [OPTIONS] 'pattern {action}' filename
324
325 1. **OPTIONS: awk的参数**
326 2. **pattern{action}: 模式动作**
327 - **pattern: 要找的对象**
328 - **{action}: 找到了之后要做的事情**
329
330 **注意:**
331
332 1. Pattern和{Action}需要用单引号引起来
333 2. Pattern是可选的。**如果不指定,awk将处理输入文件中的所有记录。如果指定一个模式,awk则只处理匹配指定的模式的记录**
334 3. {Action}为awk命令,可以是单个命令,也可以多个命令。整个Action(包括里面的所有命令)都必须放在{ }中
335 4. Action必须被{ }包裹,没有被{ }包裹的就是pattern
336 5. filename要处理的目标文件
337
338 参数说明:
339
340 - **-F 指定字段分隔符**
341 - **-v var=value 自定义变量并赋值**
342
343
344
345 内建变量(**在引用时不需要前面加$**)
346
347 | 变量 | 描述 |
348 | -------- | ------------------------------------------------------------ |
349 | $n | 当前行的第n列,字段间由FS分隔 |
350 | $0 | 整个当前行 |
351 | NFR | 各文件分别计数的行号,都从1开始 |
352 | FS | 输入字段分隔符(默认是任何空格) |
353 | NF | 每一行拥有的字段总数,**$NF表示最后一列**,**$(NF-1)表示倒数第二列** |
354 | NR | 目前处理的是第几行的数据,就是行号($NR),从1开始 |
355 | OFS | 输出字段分隔符(输出换行符),输出时用指定的符号代替换行符 |
356 | ORS | 输出行分隔符(默认值是一个换行符) |
357 | RS | 输入行分隔符(默认是一个换行符) |
358 | FILENAME | 当前文件名 |
359
360 ```powershell
361 #举栗子
362 zx@xx:[/xx/xx]cat test.txt
363 root1,root2,root3
364 user1,user2,user3
365 zhangsan,lisi,wangwu
366 123,456,789
367
368 #打印文件第一列
369 zx@xx:[/xx/xx]awk -F , '{print $1}' test.txt
370 root1
371 user1
372 zhangsan
373 123
374
375 #输出第1,3列,并以\t为分隔符
376 zx@xx:[/xx/xx]awk -F , '{print $1,$3}' OFS="\t" test.txt
377 root1 root3
378 user1 user3
379 zhangsan wangwu
380 123 789
381
382 #查找包含123的行,不包含123的行
383 zx@xx:[/xx/xx]awk '/123/' test.txt
384 123,456,789
385 zx@xx:[/xx/xx]awk '!/123/' test.txt
386 root1,root2,root3
387 user1,user2,user3
388 zhangsan,lisi,wangwu
389
390 #将test.txt文件前3行的第一,二列,以制表符分隔打印出来
391 zx@xx:[/xx/xx]cat -n test.txt
392 1 root roat www
393 2 abc dbc xxx
394 3 ney aey ddd
395 4 11 22 33
396 zx@xx:[/xx/xx]awk 'NR<4{print $1"\t"$2}' test.txt
397 root roat
398 abc dbc
399 ney aey
400 zx@xx:[/xx/xx]awk 'NR<4{print $1,$2}' OFS="\t" test.txt
401 root roat
402 abc dbc
403 ney aey
404 zx@xx:[/xx/xx]awk '{print "该行数据为"$0"\t" "该行的字段总数为"NF"\t" "目前这是第几行"NR}' test.txt
405 该行数据为root roat www 该行的字段总数为3 目前这是第几行1
406 该行数据为abc dbc xxx 该行的字段总数为3 目前这是第几行2
407 该行数据为ney aey ddd 该行的字段总数为3 目前这是第几行3
408 该行数据为11 22 33 该行的字段总数为3 目前这是第几行4
409
410
411 ```