Skip to content

Linux三剑客grep/awk/sed

About 2671 wordsAbout 9 min

linuxgrepawksed

2024-06-13

三剑客的功能非常强大,我们只需要掌握它们分别擅长的领域即可: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的帮助信息
  • 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次一个任意的字符。

Changelog

Last Updated: View All Changelog
  • feat(wiki): hammeSpoon: 复制出来的文件需要重新生成永链

    On 3/27/25

求求了,快滚去学习!!!

求求了求求了,快去学习吧!

【题单】贪心算法

不知道方向的时候,可以多看看书,书会给你指明下一步该干什么,加油!