请关注本头条号,每天坚持更新原创干货技术文章。
如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习
1. 简介
grep命令用于在文件中查找指定内容。本教程展示了一些最常见的grep命令示例,对软件开发人员特别有益。最近,我开始使用Asciidoctor.js、Asciidoctor.js-pug、Asciidoctor-templates.js项目。当您第一次深入到包含数千行代码的代码库时,高效工作并容易。但是我的秘密武器是grep。
我将通过示例与您分享如何在Linux中使用grep命令。
2. 在Linux系统上使用`grep`命令
如果您查看man手册,您将看到grep工具的简短描述:
打印匹配语法的行。但是,不要被这种简单的定义所愚弄
grep是Unix/Linux工具箱中最有用的工具之一,在处理文本文件时,有无数场合可以使用它。
最好是有真实的例子来学习它是如何工作的。因此,我将使用Asciidoctor.js源代码树来演示一些grep功能。您可以从GitHub下载源代码树,如果您愿意,您甚至可以查看我在撰写本文时使用的同一个版本。这将确保您获得的实验结果与本文其余部分描述的完全相同:
git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1
2.1 查找所有出现的字符串(基本用法)
Asciidoctor.js支持JAVA平台的Nashorn JavaScript engine,我不了解Nashorn,因此我可以利用这个机会通过研究引用该JavaScript引擎的项目部分来进一步了解它。
首先,我需要检查package.json这个文件中是否有与Nashorn依赖关系的相关描述。
shnbsp;grep nashorn package.json
"test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",
是的,显然有一些针对Nashorn-specific的测试。让我们进一步研究一下。
2.2 不区分大小写的搜索
现在,我想仔细查看一下./npm/test/目录中的文件,其中明确地提到了Nashorn。这里使用不区分大小写的搜索(i选项)可能更好,因为我需要找到对nashorn和nashorn的引用(或任何其他大小写字符的组合):
shnbsp;grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');
事实上,忽略大小写在这里是有用的。否则,我就会错过require('../module/nashorn')这样的语句。毫无疑问,我应该稍后更详细地检查该文件。
2.3 找到非匹配的文件
npm/test/目录中是否有一些非Nashorm相关的文件?为了回答这个问题,我们可以使用grep (-L选项)中的“打印非匹配文件”选项:
shnbsp;grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js
注意如何使用-L选项将grep的输出结果更改为只显示文件名。因此,上面的文件中没有一个包含字符串nashorn(不管是哪种情况)。这并不意味着它们与这项技术没有关系,但至少,字母nashorn不存在。
2.4 在隐藏文件中查找内容,并递归地向子目录中查找相关内容
最后两个命令使用shell glob模式将要检查的文件列表传递给grep命令。但是,这有一些固有的限制:星号*将不匹配隐藏文件,它也不会匹配子目录中包含的文件。
解决方案是将grep与find命令相结合,而不是依赖于shell glob语法:
# This is not efficient as it will spawn a new grep process for each file这是低效率的,因为它将为每个文件生成一个新的grep进程
nbsp;find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters这可能与包含空格字符的文件名有关
grep -iL nashorn $(find npm/test/ -type f)
正如我在上面的代码块注释中提到的,每个解决方案都有缺点。关于包含空格类型字符的文件名,可以研究一下grep -z选项,它与find命令的-print0选项结合使用,可以缓解这个问题。
然而,更好的解决方案是使用grep的“递归”-r选项。有了这个选项,您可以在命令行上给出搜索树的根(开始目录),而不是要检查的文件名的显式列表。使用-r选项,grep将检查搜索目录中的所有文件,包括隐藏的文件,然后递归深入到任何子目录:
grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js
2.5 根据文件名过滤文件(使用正则表达式)
所以,在这个项目中似乎有一些Nashorn具体测试。由于Nashorn是Java,另一个可能提出的问题是“项目中是否有一些Java源文件明确提到了Nashorn?”
根据当前使用的grep版本,至少有两个解决方案可以回答这个问题。第一个是使用grep查找包含nashorn的所有文件,然后将第一个命令的输出重定向到第二个grep实例中,过滤掉非java源文件:
sh $grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/basic.js"));
现在应该可以理解命令的前半部分了。但怎么理解“^[\^:]*\\.java”这部分呢?
除非指定-F选项,否则grep假设搜索模式是一个正则表达式。这意味着,除了与逐字匹配的普通字符之外,您还可以访问一组元字符来描述更复杂的模式。我上面使用的模式将只匹配:
- ^表示行的开头
- [^:]*后跟除冒号外的任何字符序列
- .后跟一个点(点在regex中有特殊的含义,因此我必须使用反斜杠来保护它,以表示我需要文字匹配)
在本实例中,由于grep将使用冒号将文件名与上下文分隔开,因此在filename部分中只保留具有.java的行。值得一提的是,它还可以匹配.javascript文件名。
2.6 使用`grep`按文件名过滤文件
递归搜索带nashorn关键内容的文件,忽略大小写,并且文件名以.java结尾。
shnbsp;grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/basic.js"));
2.7 查找关键字
精确匹配关键字-w选项,i忽略大小写,指定文件后缀*.js,搜索关键字opal。
shnbsp;grep -irw --include='*.js' Opal .
2.8 输出结果带颜色
选项--color为匹配选项着色。
sh $grep -irw --color=auto --include='*.js' Opal .
2.9 统计匹配内容的行数
为匹配内容统计行数:
shnbsp;grep -irw --include='*.js' Opal . | wc -l
86
这意味着我们在所有检查的文件中总共有86行匹配的行。然而,有多少不同的文件是匹配的?使用-l选项,您可以限制grep输出匹配的文件的数量,而不是显示匹配的行数。因此,这个简单的改变将告诉有多少文件是匹配的:
shnbsp;grep -irwl --include='*.js' Opal . | wc -l
20
如果这让您想起了-L选项,那么毫无疑问:因为它比较常见,所以小写/大写用于区分相反作用的选项。-l显示匹配的文件名。-L显示不匹配的文件名。另一个例子,我让您检查手册中的-h和-h选项。
选项-c统计匹配的次数。
grep -irwc --include='*.js' Opal .
3. 总结
grep命令参数一览
- -a 或 --text : 不要忽略二进制的数据。
- -A<显示行数> 或 --after-context=<显示行数> : 除了显示符合范本样式的那一列之外,并显示该行之后的内容。
- -b 或 --byte-offset : 在显示符合样式的那一行之前,标示出该行第一个字符的编号。
- -B<显示行数> 或 --before-context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前的内容。
- -c 或 --count : 计算符合样式的列数。
- -C<显示行数> 或 --context=<显示行数>或-<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前后的内容。
- -d <动作> 或 --directories=<动作> : 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
- -e<范本样式> 或 --regexp=<范本样式> : 指定字符串做为查找文件内容的样式。
- -E 或 --extended-regexp : 将样式为延伸的正则表达式来使用。
- -f<规则文件> 或 --file=<规则文件> : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
- -F 或 --fixed-regexp : 将样式视为固定字符串的列表。
- -G 或 --basic-regexp : 将样式视为普通的表示法来使用。
- -h 或 --no-filename : 在显示符合样式的那一行之前,不标示该行所属的文件名称。
- -H 或 --with-filename : 在显示符合样式的那一行之前,表示该行所属的文件名称。
- -i 或 --ignore-case : 忽略字符大小写的差别。
- -l 或 --file-with-matches : 列出文件内容符合指定的样式的文件名称。
- -L 或 --files-without-match : 列出文件内容不符合指定的样式的文件名称。
- -n 或 --line-number : 在显示符合样式的那一行之前,标示出该行的列数编号。
- -o 或 --only-matching : 只显示匹配PATTERN 部分。
- -q 或 --quiet或--silent : 不显示任何信息。
- -r 或 --recursive : 此参数的效果和指定"-d recurse"参数相同。
- -s 或 --no-messages : 不显示错误信息。
- -v 或 --revert-match : 显示不包含匹配文本的所有行。
- -V 或 --version : 显示版本信息。
- -w 或 --word-regexp : 只显示全字符合的列。
- -x --line-regexp : 只显示全列符合的列。
- -y : 此参数的效果和指定"-i"参数相同。
本文已同步至博客站,尊重原创,转载时请在正文中附带以下链接:https://www.linuxrumen.com/cyml/1690.html
点击了解更多,快速查看更多的技术文章列表。