grep
1.命令格式:
grep [option] pattern file
2.命令功能:
用于过滤/搜索的特定字符。可使用正则表达式能多种命令配合使用,使用上十分灵活。
3.命令参数:
-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 #在显示符合样式的那一行之前,标示出该行的列数编号。
-q --quiet或--silent #不显示任何信息。
-r --recursive #此参数的效果和指定“-d recurse”参数相同。
-s --no-messages #不显示错误信息。
-v --revert-match #显示不包含匹配文本的所有行。
-V --version #显示版本信息。
-w --word-regexp #只显示全字符合的列。
-x --line-regexp #只显示全列符合的列。
-y #此参数的效果和指定“-i”参数相同。
4.规则表达式:
grep的规则表达式:
^ #锚定行的开始 如:'^grep'匹配所有以grep开头的行。
$ #锚定行的结束 如:'grep$'匹配所有以grep结尾的行。
. #匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。
* #匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。
.* #一起用代表任意字符。
[] #匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。
[^] #匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。
\(..\) #标记匹配字符,如'\(love\)',love被标记为1。
\< #锚定单词的开始,如:'\<grep'匹配包含以grep开头的单词的行。
\> #锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行。
x\{m\} #重复字符x,m次,如:'0\{5\}'匹配包含5个o的行。
x\{m,\} #重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。
x\{m,n\} #重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。
\w #匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。
\W #\w的反置形式,匹配一个或多个非单词字符,如点号句号等。
\b #单词锁定符,如: '\bgrep\b'只匹配grep。
POSIX字符:
为了在不同国家的字符编码中保持一至,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如[:alnum:]是[A-Za-z0-9]的另一个写法。要把它们放到[]号内才能成为正则表达式,如[A- Za-z0-9]或[[:alnum:]]。在linux下的grep除fgrep外,都支持POSIX的字符类。
[:alnum:] #文字数字字符
[:alpha:] #文字字符
[:digit:] #数字字符
[:graph:] #非空字符(非空格、控制字符)
[:lower:] #小写字符
[:cntrl:] #控制字符
[:print:] #非空字符(包括空格)
[:punct:] #标点符号
[:space:] #所有空白字符(新行,空格,制表符)
[:upper:] #大写字符
[:xdigit:] #十六进制数字(0-9,a-f,A-F)
使用正则表达式的一个多用途文本搜索工具. 这个命令本来是ed行编辑器中的一个命令/过滤器: g/re/p -- global - regular expression - print.
grep pattern [file...]
在文件中搜索所有pattern出现的位置, pattern既可以是要搜索的字符串, 也可以是一个正则表达式.
bash$ grep '[rst]ystem.$' osinfo.txt The GPL governs the distribution of ... Linux operating system.
如果没有指定文件参数, grep通常用在管道中对stdout进行过滤.
bash$ ps ax | grep clock 765 tty1 S 0:00 xclock 901 pts/1 S 0:00 grep clock
-i
选项在搜索时忽略大小写.-w
选项用来匹配整个单词.-l
选项仅列出符合匹配的文件, 而不列出匹配行.-r
(递归) 选项不仅在当前工作目录下搜索匹配, 而且搜索子目录.-n
选项列出所有匹配行, 并显示行号.bash$ grep -n Linux osinfo.txt 2:This is a file containing information about Linux. 6:The GPL governs the distribution of the Linux operating system.
-v
(或者--invert-match
)选项将会显示所有不匹配的行.1 grep pattern1 *.txt | grep -v pattern2 2 3 # 匹配在"*.txt"中所有包含 "pattern1"的行, 4 # 而***不显示***匹配包含"pattern2"的行.
-c
(--count
) 选项将只会显示匹配到的行数的总数,而不会列出具体的匹配.1 grep -c txt *.sgml # (在 "*.sgml" 文件中, 匹配"txt"的行数的总数.) 2 3 4 # grep -cz . 5 # ^ 点 6 # 意思是计数 (-c) 所有以空字符分割(-z) 的匹配 "."的项 7 # "."是正则表达式的一个符号, 表达匹配任意一个非空字符(至少要包含一个字符). 8 # 9 printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz . # 3 10 printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '$' # 5 11 printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '^' # 5 12 # 13 printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -c '$' # 9 14 # 默认情况下, 是使用换行符(\n)来分隔匹配项. 15 16 # 注意 -z 选项是 GNU "grep" 特定的选项. 17 18 19 # 感谢, S.C.
当有多个文件参数的时候, grep将会指出哪个文件中包含具体的匹配.
bash$ grep Linux osinfo.txt misc.txt osinfo.txt:The GPL governs the distribution of the Linux... misc.txt:The Linux operating system is steadily ...
如果存在一个成功的匹配, 那么grep命令将会返回0作为退出状态码, 这样就可以将grep命令的结果放在脚本的条件测试中来使用, 尤其和
-q
(禁止输出)选项组合时特别有用.1 SUCCESS=0 # 如果grep匹配成功 2 word=Linux 3 filename=data.file 4 5 grep -q "$word" "$filename" # "-q"选项将使得什么都不输出到stdout上. 6 7 if [ $? -eq $SUCCESS ] 8 # if grep -q "$word" "$filename" 这句话可以代替行 5 - 7. 9 then 10 echo "$word found in $filename" 11 else 12 echo "$word not found in $filename" 13 fi
例子 29-6展示了如何使用grep命令在一个系统logfile中进行一个单词的模式匹配.
例子 12-15. 在脚本中模拟"grep"的行为
1 #!/bin/bash 2 # grp.sh: 一个非常粗糙的'grep'命令的实现. 3 4 E_BADARGS=65 5 6 if [ -z "$1" ] # 检查传递给脚本的参数. 7 then 8 echo "Usage: `basename $0` pattern" 9 exit $E_BADARGS 10 fi 11 12 echo 13 14 for file in * # 遍历$PWD下的所有文件. 15 do 16 output=$(sed -n /"$1"/p $file) # 命令替换. 17 18 if [ ! -z "$output" ] # 如果"$output"不加双引号将会发生什么? 19 then 20 echo -n "$file: " 21 echo $output 22 fi # sed -ne "/$1/s|^|${file}: |p" 这句与上边这段等价. 23 24 echo 25 done 26 27 echo 28 29 exit 0 30 31 # 练习: 32 # ----- 33 # 1) 在任何给定的文件中,如果有超过一个匹配的话, 在输出中添加新行. 34 # 2) 添加一些特征.
如何使用grep命令来搜索两个(或两个以上)独立的模式? 如果你想在一个或多个文件中显示既匹配"pattern1"又匹配"pattern2"的所有匹配的话, 那又该如何做呢? (译者: 这是取交集的情况, 如果取并集该怎么办呢?)
一个方法是通过管道来将grep pattern1的结果传递到grep pattern2中.
比如, 给定如下文件:
1 # 文件名: tstfile 2 3 This is a sample file. 4 This is an ordinary text file. 5 This file does not contain any unusual text. 6 This file is not unusual. 7 Here is some text.
现在, 让我们在这个文件中搜索既包含 "file"又包含"text"的所有行.
bash$ grep file tstfile# 文件名: tstfile This is a sample file. This is an ordinary text file. This file does not contain any unusual text. This file is not unusual.bash$ grep file tstfile | grep textThis is an ordinary ... This file does not contain any unusual text.
egrep - 扩展的grep - 这个命令与grep -E等价. 这个命令用起来有些不同, 由于使用正则表达式的扩展集合, 将会使得搜索更具灵活性. 它也允许逻辑|(或)操作.
bash $ egrep 'matches|Matches' file.txtLine 1 matches. Line 3 Matches. Line 4 contains matches, but also Matches
fgrep - 快速的grep - 这个命令与grep -F等价. 这是一种按照字符串字面意思进行的搜索(即不允许使用正则表达式), 这样有时候会使搜索变得容易一些.
在某些Linux发行版中, egrep和fgrep都是grep命令的符号链接或者别名, 只不过在调用的时候分别使用了
-E
和-F
选项罢了.例子 12-16. 在1913年的韦氏词典中查找定义
1 #!/bin/bash 2 # dict-lookup.sh 3 4 # 这个脚本在1913年的韦氏词典中查找定义. 5 # 这本公共词典可以通过不同的 6 #+ 站点来下载,包括 7 #+ Project Gutenberg (http://www.gutenberg.org/etext/247). 8 # 9 # 在使用本脚本之前, 10 #+ 先要将这本字典由DOS格式转换为UNIX格式(只以LF作为行结束符). 11 # 将这个文件存储为纯文本形式, 并且保证是未压缩的ASCII格式. 12 # 将DEFAULT_DICTFILE变量以path/filename形式设置好. 13 14 15 E_BADARGS=65 16 MAXCONTEXTLINES=50 # 显示的最大行数. 17 DEFAULT_DICTFILE="/usr/share/dict/webster1913-dict.txt" 18 # 默认的路径和文件名. 19 # 在必要的时候可以进行修改. 20 # 注意: 21 # ----- 22 # 这个特定的1913年版的韦氏词典 23 #+ 在每个入口都是以大写字母开头的 24 #+ (剩余的字符都是小写). 25 # 只有每部分的第一行是以这种形式开始的, 26 #+ 这也就是为什么搜索算法是下边的这个样子. 27 28 29 30 if [[ -z $(echo "$1" | sed -n '/^[A-Z]/p') ]] 31 # 必须指定一个要查找的单词, 32 #+ 并且这个单词必须以大写字母开头. 33 then 34 echo "Usage: `basename $0` Word-to-define [dictionary-file]" 35 echo 36 echo "Note: Word to look up must start with capital letter," 37 echo "with the rest of the word in lowercase." 38 echo "--------------------------------------------" 39 echo "Examples: Abandon, Dictionary, Marking, etc." 40 exit $E_BADARGS 41 fi 42 43 44 if [ -z "$2" ] # 也可以指定不同的词典 45 #+ 作为这个脚本的第2个参数传递进来. 46 then 47 dictfile=$DEFAULT_DICTFILE 48 else 49 dictfile="$2" 50 fi 51 52 # --------------------------------------------------------- 53 Definition=$(fgrep -A $MAXCONTEXTLINES "$1 \\" "$dictfile") 54 # 以 "Word \..." 这种形式定义 55 # 56 # 当然, 即使搜索一个特别大的文本文件的时候 57 #+ "fgrep"也是足够快的. 58 59 60 # 现在, 剪掉定义块. 61 62 echo "$Definition" | 63 sed -n '1,/^[A-Z]/p' | 64 # 从输出的第一行 65 #+ 打印到下一部分的第一行. 66 sed '$d' | sed '$d' 67 # 删除输出的最后两行 68 #+ (空行和下一部分的第一行). 69 # --------------------------------------------------------- 70 71 exit 0 72 73 # 练习: 74 # ----- 75 # 1) 修改这个脚本, 让它具备能够处理任何字符形式的输入 76 # + (大写, 小写, 或大小写混合), 然后将其转换为 77 # + 能够处理的统一形式. 78 # 79 # 2) 将这个脚本转化为一个GUI应用, 80 # + 使用一些比如像"gdialog"的东西 . . . 81 # 这样的话, 脚本将不再从命令行中 82 # + 取得这些参数. 83 # 84 # 3) 修改这个脚本让它具备能够分析另外一个 85 # + 公共词典的能力, 比如 U.S. Census Bureau Gazetteer.
agrep (近似grep)扩展了grep近似匹配的能力. 搜索的字符串可能会与最终匹配结果所找到字符串有些不同. 这个工具并不是核心Linux发行版的一部分.
为了搜索压缩文件, 应使用zgrep, zegrep, 或zfgrep. 这些命令也可以对未压缩的文件进行搜索, 只不过会比一般的grep, egrep, 和fgrep慢上一些. 当然, 在你要搜索的文件中如果混合了压缩和未压缩的文件的话, 那么使用这些命令是非常方便的.
如果要搜索bzipped类型的文件, 使用bzgrep.
--摘自ABS
补充:
2017.05.11
Linux系统下比较两个文件并删除相同部分
方法一: comm -23 file1 file2 方法二: grep -v -f file1 file2 /*注::此法在对比数字时候比较凑效果,文本对比不建议使用*/ 方法三: awk '{print NR,$0}' file1 file2 |sort -k2|uniq -u -f 1|sort -k1|awk '{print $2}' 或者: awk '{print $0}' file1 file2 |sort|uniq -u |
1、统计两个文本文件的相同行 grep -Ff file1 file2 2、统计file1中有,file2中没有的行 grep -vFf file1 file2 grep -Fvxf <(grep -Fxf file1 file2 ) file1 file2 如何比较两个文件并去删除相同的内容 for i in $(<file1); do grep $i file2 || echo $i >>tmp1 ; done 输出相同行: $grep -wf file1 file2 输出不同行 $grep -wvf file1 file2 |