相关文章 【linux命令】find命令、grep命令(正则表达式)

概述

find 是用来搜索文件的,结果是文件列表
grep 是用来搜索文本的, 用来在standard input或文件内部的内容中, 来搜索文字 内容的!,结果是字符串,也会把归属的文件列出来

find 是完全匹配(通配符),而grep是包含匹配(正则表达式),参见 【Linux】Shell正则表达式与通配符的区别

1. find

find 路径 -name 表达式

注意:

  • 目标文件的表达式为模糊匹配,表达式带号,需要加引号,比较保险,例如 find . -name '.tar.gz’
    原因参见1.1.1 章节

  • 目标文件的表达式为全称,表达式不带*号,可以加引号,也可以不加 find . -name jdk.tar.gz

  • find 是完全匹配(通配符);

  • find 默认是递归查询,即会查询子文件夹下

1.1 常见错误

1.1.1 find: paths must precede expression:

问题语句 find . -name *.txt,会报find: paths must precede expression错误

解决方案:这个语句中包含*号,需要加引号: find . -name '*.txt'

原因:* 号对于shell来说是个特殊含义,指代当前目录下的所有文件,若存在 1.txt 2.txt 3.txt ,即
find . -name *.txt 等价于 find . -name 1.txt 2.txt 3.txt,-name属性后面跟了3个参数,而我们模板中的参数只能有一个,因此需要加上引号。

2. grep命令

grep 查找文件里符合条件的字符串,常与 管道符|、cat、ps一起使用;主要用于查找文件中符合条件的字符串、统计文件中符合条件的字符串行数

基本格式:

  • grep [options] [查找条件(正则表达式)] [目标文件]

  • 与管道符一起用 cat test.txt | grep hello

grep不能搜索目录,如果想搜索子目录下的所有文件,通过-r参数
grep -r “查询内容” 文件目录

  • 如果不含空格、变量,可以不加引号

  • 空格必须加引号
    单引号,双引号的区别在于双引号支持变量 “$name”,而单引号会把整个内容全部当做普通字符 ,在shell脚本中由其要注意

    [root]$  a='abc';echo 'abcd'| grep '$a'  //打印空,因为单引号把变量当做普通字符串
    [root]$  a='abc';echo 'abcd'| grep "$a"  //双引号匹配到结果
    
  • 如果含有特殊字符,需要加上转义字符

2.1.可选参数

grep --help 查看更多参数

[options]主要参数:

-i:不区分大小写
-n:显示匹配行及行号。
-s:不显示“不存在或无匹配文本”的错误信息。   
-E:开启扩展的正则表达式,使用egrep命令 (egrep官网已经弃用了?)
-c:计算找到’搜寻字符串’的次数,即统计行数
-o:只显示被漠视匹配到的字符串,shell默认显示匹配到文本的整行,-o 参数和java正则达到统一
-v:反向选择,即输出没有匹配到的那些字符
–color=auto:可以将找到的关键词部分加上颜色的显示!
-w:表示精确匹配一个字符
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-A选项,是 After 的缩写,表示除了展示匹配行之外,还要展示出匹配行下面的若干行。而示例中的 -A 1 则表示还展示匹配行下面一行的内容。
-B选项,是 Before 的缩写,表示除了展示匹配行之外,还要展示出匹配行上面的若干行。而示例中的 -B 1 则表示还展示匹配行上面一行的内容。
-C:前后多少行,等于 -A 和 -B效果之和

grep -B 1 pattern file

-B选项,是 Before 的缩写,表示除了展示匹配行之外,还要展示出匹配行上面的若干行。而示例中的 -B 1 则表示还展示匹配行上面一行的内容。

2.2 正则表达式

pattern正则表达式主要参数:

^匹配输入字符串的开始位置。除非在方括号表达式中使用,表示不包含该字符集合。要匹配"^"字符本身,需要转移"\^"
$匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则"$"也匹配'\n'或'r'
.“.”代表除"\n\s"之外的任何单个字符, { } 需要添加 转义字符
\反斜杠,又叫转义字符,去除其后紧跟的元字符或通配符的 特殊意义
*匹配前面的子表达式零次或多次。要匹配"*"字符,要进行\转移
[ ]字符集合,匹配所包含的任意的一个字符
[^]复制字符集。匹配未包含在[ ]内的任意一个字符
[n1-n2]字符范围。匹配指定范围内的任意一个字符。例如[a-z]可以匹配到a到z范围内的任意一个小写字母字符
{n}n是一个非负整数,匹配确定的n次,例如“o{2}”不能匹配“Bob”中的“o”,但是能匹配到“food”中的“oo”,并且 { } 需要添加 转义字符
{n,}n是一个非负整数,至少(最少)匹配n次。例如,“o{2,}”不能匹配"Bob"中的“o”,但是能匹配“fooooood”中的所有o。“o{1.}”等于“o+”
{n,m}

n和m均为非负整数,其中n<=m,最少匹配n次,最多匹配m次

由于在双引号中,"${name}"具有引用变量的含义,因此 上述正则表达式中 { } 需要转义字符,否则不识别为正则规则,此外还有 点号也需要转义

需要注意:shell的正则语法和java的正则语法稍有不同,例如前者不支持 \d 这种简化的语法来判断全数字,有关java更多的语法,参见 Java 正则表达式

2.2.实例

目录要带-r,表示递归查询

2.2.1 显示所有以d开头的文件中包含 test的行

grep 'test' d*

2.2.2 显示在aa,bb,cc文件中包含test的行

grep 'test' aa bb cc

2.2.3 显示所有包含每行字符串至少有5个连续小写字符的字符串的行,注意转义字符

创建一个test.txt

aa
3d
cccc
abcde
abEllde

grep '[a-z]\{5\}' test.txt   //带转义字符,输出abcde
grep '[a-z]{5}' test.txt  //不带转义字符,无输出

不管是单引号还是双引号,都要转义

2.2.4 显示/usr/src目录下的文件(不含子目录)包含magic的行

grep magic /usr/src

2.2.5 显示/usr/src目录下的文件(包含子目录)包含magic的行

grep -r magic /usr/src

2.2.6 只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’)

grep -w magic test.txt 

2.2.7 展示相邻行

除了展示搜到的内容所在行以外,多显示前面3行,后面2行,及总共多显示5行

grep -A 2 -B 3 ‘something’ a.txt

前后各5行: grep -C 5 ‘something’ a.txt

2.2.8 或 匹配

grep ‘pg|postgresql’ 注意\|跟前后pattern要连着

2.3 反例

由于grep 后面的是正则,如果混淆为通配符,会产生非预期的结果,参见【linux命令】find命令、grep命令(正则表达式)

参考

Linux:正则表达式
《path must precede expression错误》
《find:paths must precede expression问题及解决》

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐