Linux三剑客grep/awk/sed
三剑客的功能非常强大,我们只需要掌握它们分别擅长的领域即可:grep擅长查找,sed擅长取行和替换,awk擅长取列。
计划将时间拉长来学习这三个命令,从今天7月8号开始。
推荐阅读的文章: 玩转文本三剑客:grep/sed/AWK的高效用法和实战技巧
Linux Grep 命令
grep(global regular expression)命令用于查找文件里面符合条件的字符串或者正则表达式。
grep指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名,或是所给予的文件名为-, 则grep指令会从标准输入设备读取数据。
格式
命令
-d<动作>: 当指定要查找的是目录而非文件的时候,必须使用这项参数,否则grep指令将回报信息并停止动作。
-r:此参数的效果和指定“-d recurse”参数相同。
-n:显示匹配行的行号。
-B:除了显示符合样式的那一行之外,并显示该行之前的内容。
-c:计算符合样式的列数, 如果有\n将字符串换行,将会多算一个。
-C: 除了显示匹配指定模式的行之外,还会显示该行之前和之后的如果干行。
-e:指定字符串做为查找文件内容的样式。grep -e '^hello' file.txt
-E:启用正则表达式
-i:查找不区分大小写grep -i "hellO" file.txt
-w:只显示全字符合的列,就是全部匹配才算
-n:在显示符合样式的那一行的同时,输入该行的列数编号。
-l:输入匹配上的文件的文件名称
实例
1 在文件file.txt中查找字符串hello, 并打印匹配的行:
grep hello file.txt
2 在文件夹dir中递归查找所有文件中匹配正则表达式“pattern”的行,并打印匹配行所在的文件名和行号:
grep -r -n pattern dir/
3 在标准输入中查找字符串“world”, 并只打印匹配的行数:
echo "hello world" | grep -c world
4 在当前目录中,查找后缀有file字样的文件中包含test字符串的文件,并打印出该字符串的行;
grep test *file
5 以递归的方式查找符合条件的文件。例如,查找指定目录/etc/acpi及其子目录下所有文件中包含字符串“update”的文件,并打印出该字符串所在的内容;
grep -r update /etc/acpi
6 在文件内容查找与正则表达式匹配的行:
grep -e '正则表达式' 文件名
grep -e "apple" -e "banana" file.txt // 查找包含apple或者banana的行
grep -e "^hello" -e "world\$" file.txt // 查找以hello开头或者world结尾的内容
7 从根目录开始查找所有扩展名为.log的文本文件,并找到包含ERROR的行:
find / -type f -name "*.log" | xargs grep "ERROR" // -type 表示类型, -name 名字
这里为什要用xargs? 第一因为有些命名不是从标注输入获取的数据源。参考:Linux xargs命令的理解和使用
我们看两个例子
(base) ➜ jet5devil-index (dev0) ✗ echo '--help' | cat
--help
(base) ➜ jet5devil-index (dev0) ✗ echo '--help' | xargs cat
cat: illegal option -- -
usage: cat [-belnstuv] [file ...]
对于第一个命令就是说,echo的内容当作了cat处理的文件内容;简单来理解就是,有一个文件 tmp.txt,它的内容及时--help
第二个的话,就是吧--help做为cat的一个命令参数来运行
场景
1 系统报警显示了时间,但是日志文件太大了无法直接cat查看。(查询含有特定文本的文件,并拿到这些文本所在的行)。
grep -n '2024-07-08 00:01:11' *.log
2 获取到错误信息的行数,需要输出上下20行的内容
grep -C 20 'hello world' *.log
Linux Awk命令
awk是一种处理文本文件的语言,是一个强大的文本分析工具。
语法
awk options 'pattern {action}' file
Options: 是一些选项,用于控制awk行为
- -F:指定输入字段分隔符,默认是空格;例如:
awk -F ':' '{print $1}' demo.txt
, -F后面的分隔符可以不用单引号包,可以直接-F:
- -v <变量名>=<值>:设置awk内部的变量
- -f:
- -v:显示awk的版本信息
- -h:显示awk的帮助信息
- -F:指定输入字段分隔符,默认是空格;例如:
pattern:用于匹配输入数据的模式。如果省略,则awk将对所有行进行操作
{action}:是在匹配到模式的行上执行的动作,如果省略,则默认动作是打印整行
实例
awk '{print $0}' demo.txt
上面实例,de mo.txt是awk要处理的文件,前面单引号内部有一个大括号,里面就是每一行处理的动作print $0, 其中,print是打印命令,$0代表当前行,因此上面的命令执行的结果就是把每一行原样打印出来。
echo 'this is a test' | awk '{print $0}' // 输出 this is a test
echo 'this is a test' | awk '{print $1}' // 输出 this
awk会根据空格和制表符,将每一行分成若干字段,一次用$1, $2, $3 代表第一个字段,第二个字段,第三个字段等等。
变量
变量NF表示当前有多少个字段,因此$NF就代表最后一个字段。
echo 'this is a test' | awk '{print $NF}' // 输入 test
$(NF-1)就表示倒数第二个字段,下面print命令里面的都好,表示输出的时候,两个部分之间使用空格分开。
awk -F ':' '{print $1, $(NF-1)}' demo.txt
变量NR表示当前处理的是第几行。
awk -F ':' '{print NR ")" $1}' demo.txt // 输出行数 + ) + 第一个字段
awk的其他内置变量如下:(需要区分大小写)
- FILENAME: 当前文件名
- FS:字段分隔符,默认是空格和制表符
- RS:行分隔符,用于分隔每一行,默认是换行符
- OFS:输出字段分隔符
- ORS:输出记录分隔符
- OFMT:输出输出的格式,默认为%.6g
函数
awk还提供了一些内置函数,方便对原始数据处理。
awk -F ':' '{print toupper($1)}' demo.txt // toupper() 将字符转为大写
其他常用函数:
tolower()
: 字符串转为小写length()
:返回字符串长度awk 'length>3' log.txt
substr()
:返回子字符串sin()
:正弦cos()
:余弦sqrt()
:平方根rand()
:随机数
条件
awk允许指定输入条件,结果只输入满足条件的行。awk '条件 动作' 文件名
awk -F ':' '/usr/ {print $1}' demo.txt // print前面是一个正则表达式,只输出usr的行
awk -F ':' 'NR % 2 == 1 {print $1}' demo.txt // 只输出奇数行, 这里NR % 2 == 就是选择奇数行
awk -F ':' 'NR > 3 {print $1}' demo.txt // 只输出行数大于三的行
awk -F ':' '$1 == "root" {print $0}' demo.txt // 只输出第一个字段是root的行
awk -F ':' '$1 == "root" || $1 == "bin" {print $0}' demo.txt // 输出第一个字段是root或者是bin的行
IF语句
awk提供if语句,用于编写复杂的的条件
awk -F ':' '{if($1 > "a") print $0}' demo.txt // 输出第一个字段第一个字符大于a的行
awk -F ':' '{if($1 > "a") print $1; else print "---"}' demo.txt // 使用if else语句
扩展
1计算当前文件夹下面所有*.log
文件的大小, ls -l *.txt | awk '{sum += $5} END {print sum}'
Linux Sed命令
参考:Linux | sed文本处理,从入门到精通,看这一篇就够了
Linux sed 命令是利用脚本来处理文本文件, sed可依照脚本的指令来处理/编辑文本文件,主要用来自动编辑一个或者多个文件/简化对文件的反复操作/便携转换程序。
对于sed命令,他不会修改原始文件的内容,是将原始文件内容做处理之后输出出来。
语法
参数说明
sed [-hnv] [-e<script>][-f<script文件>][文本文件]
-e<script> 指定script的来处理输入的文本文件。
-f<script文件> 指定script文件来处理输入的文本文件。
-h 帮助
-n 仅展示script处理后的结果, 只显示匹配并处理过的行(就是说只展示处理的行,没处理的行就不展示)
sed -n '5p' demo.txt // 展示第五行
sed -n '1,5p' demo.txt // 展示第1到第5行
sed -n '1p;5p' demo.txt // 展示第一行和第五行
sed -n '5, 100!p' demo.txt // 取反 取第1行到第4行
sed -n '2, +2p' demo.txt // 显示第2行和其后面的两行
sed -n '$p' demo.txt // 展示最后一行
sed -n '1~3p' demo.txt // 从第一行起,每件个3行输出一行
-V 显示版本信息
-r 表示启用扩展正则表达式,echo "123abc" | sed -r 's/[0-9]+/num/'
-> numabc
动作说明
a 新增, a的后面可以接字符串,这些字串会在新的一行出现,目前是下一行。
c 取代, c的后面可以接字串,
d 删除,因为是删除,所以d后面不接任何东西。
i 插入, i后面可以接字串,会在新的一行出现,目前是上一行。
p 打印
s 取代, 可以直接进行取代的工作。s可以搭配正则表达式,例如 1,20s/old/new/g
实例
sed命令将所有的空格换成等于=, sed 's/ /=/g' example.txt
将数字换成字母d , sed 's/[0-9]/d/g' example.txt
原始文件:
(base) ➜ github cat demo.txt
Linux
Solaris
Ubuntu
Fedora
RedHat
删除所有的字母a。sed 's/a//g' demo.txt
, 删除掉第一个字母 a sed 's/a//' demo.txt
, g表示global的意思,如果带上这个参数就是对所有匹配上的内容使用。
2 移除每一行的第一个字母 sed 's/^.//' demo.txt
, .
表示匹配一个字符,^
表示以什么开头的意思; sed 's/.//' demo.txt
也可以达到相同的效果,因为sed是从头开始匹配的。
3 移除每一行的最后一个字母 sed 's/.$//' demo.txt
, $
会匹配每一行的结尾。
4 同时移除每一行开头第一个字母和结尾第一个字母 sed 's/.//;s/.$//' demo.txt
, sed命令结合多个操作指令时,每个指令通过 ;
分隔。
5 删除每一行的第一个到第n个字符 sed -r 's/.{4}//' demo.txt
.{n}
匹配n次一个任意的字符。