【BASH】回顾与知识点梳理 十一
- 十一. 八至十章知识点总结及练习
- 11.1 总结
- 11.2 练习
- 情境模拟题一:透过 grep 搜寻特殊字符串,并配合数据流重导向来处理大量的文件搜寻问题。
- 情境模拟题二:使用管线命令配合正规表示法建立新指令与新变量。
该系列目录 --> 【BASH】回顾与知识点梳理(目录)
十一. 八至十章知识点总结及练习
11.1 总结
- 正规表示法就是处理
字符串
的方法,他是以行
为单位来进行字符串的处理行为; - 正规表示法透过一些特殊符号的辅助,可以让使用者轻易的达到『搜寻/删除/取代』某特定字符串的处理程
序;(grep,sed nd,sed nc string) - 只要工具程序支持正规表示法,那么该工具程序就可以用来作为正规表示法的字符串处理之用;(grep sed)
- 正规表示法与通配符是完全不一样的东西!
通配符
(wildcard) 代表的是bash 操作接口
的一个功能, 但正规表示法
则是一种字符串处理
的表示方式! - 使用 grep 或其他工具进行正规表示法的字符串比对时,因为编码的问题会有不同的状态,因此, 你最好将 LANG 等变量设定为 C 或者是 en 等英文语系!
- grep 与 egrep 在正规表示法里面是很常见的两支程序,其中, egrep 支持更严谨的正规表示法的语法;
grep -e
- 由于编码系统的不同,不同的语系 (LANG) 会造成正规表示法撷取资料的差异。因此可利用特殊符号如
[:upper:]
来替代编码范围较佳; - 由于严谨度的不同,正规表示法之上还有更严谨的延伸正规表示法;
- 基础正规表示法的特殊字符有:
*, ., [], [-], [^], ^, $
等!扩展正则表达式特殊字符有:+, ?, |, (), ()+
- 常见的支持正规表示法的工具软件有: grep , sed, vim 等等
- printf 可以透过一些特殊符号来将数据进行格式化输出;(s,i,f \t \n \v)
- awk 可以使用『字段』为依据,进行数据的重新整理与输出;($1 $2… NF,NL,FS,if-else)
- 文件的比对中,可利用 diff 及 cmp 进行比对,其中 diff 主要用在纯文本文件方面的新旧版本比对 (diff -Naur)
- patch 指令可以将旧版数据更新到新版 (主要亦由 diff 建立 patch 的补丁来源文件) (-p0, -R)
11.2 练习
情境模拟题一:透过 grep 搜寻特殊字符串,并配合数据流重导向来处理大量的文件搜寻问题。
- 目标:正确的使用正规表示法;
- 前提:需要了解数据流重导向,以及透过子指令 $(command) 来处理档名的搜寻;
我们简单的以搜寻星号 (*) 来处理底下的任务:
- 利用正规表示法找出系统中含有某些特殊关键词的文件,举例来说,找出在 /etc 底下含有星号 (*) 的
文件与内容
:
解决的方法必须要搭配通配符,但是星号本身就是正规表示法的字符,因此需要如此进行(名称带*的文件没有,用.
代替举例):
[root@node-135 passwd]# grep '\*' /etc/* 2>/dev/null
Binary file /etc/aliases.db matches
/etc/bashrc: xterm*|vte*)
/etc/bashrc: PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
/etc/bashrc: screen*)
/etc/bashrc: PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
/etc/bashrc: *)
...
你必须要注意的是,在单引号内的星号是正规表示法的字符,但我们要找的是星号,因此需要加上跳脱字符 (\)。但是在 /etc/* 的那个 * 则是 bash 的通配符! 代表的是文件的档名喔!不过由上述的这个结果中,我们仅能找到 /etc 底下第一层子目录的数据,无法找到次目录的数据, 如果想要连同完整的 /etc 次目录数据,就得要这样做:
grep '\*' $(find /etc -type f ) 2> /dev/null
[root@node-135 passwd]# find /etc -type f|wc -l
1768
# 如果只想列出档名而不要列出内容的话,使用底下的方式来处理即可喔!
[dmtsai@study ~]$ grep -l '\*' $(find /etc -type f ) 2> /dev/null
- 但如果文件数量太多呢?如同上述的案例,如果要找的是全系统 (/) 呢?你可以这样做:
grep '\*' $(find / -type f 2> /dev/null )
-bash: /usr/bin/grep: Argument list too long
真要命!由于指令列的内容长度是有限制的,因此当搜寻的对象是整个系统时,上述的指令会发生错误。那该如何是好? 此时我们可以透过管线命令以及 xargs 来处理。举例来说,让 grep 每次仅能处理 10 个档名,此时你可以这样想:
a. 先用 find 去找出文件;
b. 用 xargs 将这些文件每次丢 10 个给 grep 来作为参数处理;
c. grep 实际开始搜寻文件内容。
所以整个作法就会变成这样:
find / -type f 2> /dev/null | xargs -n 10 grep '\*'
- 从输出的结果来看,数据量实在非常庞大!那如果我只是想要知道檔名而已呢?你可以透过 grep 的功能来找到如下的参数!
find / -type f 2> /dev/null | xargs -n 10 grep -l '\*'
情境模拟题二:使用管线命令配合正规表示法建立新指令与新变量。
我想要建立一个新的指令名为 myip ,这个指令能够将我系统的 IP 捉出来显示。而我想要有个新变量,变量名为 MYIP ,这个变量可以记录我的 IP 。
我们可以这样试看看:
- 首先,我们依据本章内的 ifconfig, sed 与 awk 来取得我们的 IP ,指令为:
[root@node-135 passwd]# ifconfig |grep 'inet.*netmask'|sed -e 's/^.*inet //g' -e 's/ net.*$//g'
192.168.81.106
192.168.17.135
127.0.0.1
- 再来,我们可以将此指令利用 alias 指定为 myip 喔!如下所示:
[root@node-135 passwd]# alias myip="ifconfig |grep 'inet.*netmask'|sed -e 's/^.*inet //g' -e 's/ net.*$//g'"
- 最终,我们可以透过变量设定来处理 MYIP 喔!
[root@node-135 passwd]# MYIP=$(myip)
[root@node-135 passwd]# echo $MYIP
192.168.81.106 192.168.17.135 127.0.0.1
- 如果每次登入都要生效,可以将 alias 与 MYIP 的设定那两行,写入你的 ~/.bashrc 即可!
简答题部分:
- 我想要知道,在 /etc 底下,只要含有 XYZ 三个字符的任何一个字符的那一行就列出来,要怎样进行?
[root@node-135 passwd]# grep [XYZ] /etc/* 2>/dev/null|wc -l
687
[root@node-135 passwd]# egrep 'X|Y|Z' /etc/* 2>/dev/null|wc -l
687
- 将 /etc/kdump.conf 内容取出后,(1)去除开头为 # 的行 (2)去除空白行 (3)取出开头为英文字母的那几行 (4)最终统计总行数该如何进行?
[root@node-135 passwd]# egrep -v '^#|^$' /etc/kdump.conf |grep '^[a-zA-Z]' |wc -l
2
[root@node-135 passwd]# egrep -v '^#|^$' /etc/kdump.conf |egrep '^[a-zA-Z].*' |wc -l
2
[root@node-135 passwd]# grep -v '^#' /etc/kdump.conf | grep -v '^$' | grep '^[[:alpha:]]' | wc -l
2
该系列目录 --> 【BASH】回顾与知识点梳理(目录)