- 正则表达式 Linux Shell 脚本编程(5)—文本过滤(正则表达式)
- grep 命令 Linux Shell 脚本编程(6)—文本过滤(grep命令)
- find
- awk
- sed
- 合并与分割(sort、uniq、join、cut、paste、split)
按照行方式处理文本。。。。
grep 命令格式:
选项
-a 不要忽略二进制数据。
-A<显示列数> 除了显示符合范本样式的那一行之外,并显示该行之后的内容。
-b 在显示符合范本样式的那一行之外,并显示该行之前的内容。
-c #计算符合范本样式的列数。 (只输出匹配行的计数)
-C<显示列数>或-<显示列数> 除了显示符合范本样式的那一列之外,并显示该列之前后的内容。
-d<进行动作> 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。
-e<范本样式> #指定字符串作为查找文件内容的范本样式。
-E #将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式。
-f<范本文件> 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。
-F 将范本样式视为固定字符串的列表。
-G 将范本样式视为普通的表示法来使用。
-h #在显示符合范本样式的那一列之前,不标示该列所属的文件名称。
-H 在显示符合范本样式的那一列之前,标示该列的文件名称。
-i 胡列字符大小写的差别。
-l 列出文件内容符合指定的范本样式的文件名称。
-L 列出文件内容不符合指定的范本样式的文件名称。
-n #在显示符合范本样式的那一列之前,标示出该列的编号。 (显示匹配行及行号)
-q 不显示任何信息。
-R/-r 此参数的效果和指定“
-d recurse”参数相同。
-s #不显示错误信息。
-v #反转查找。 ---显示不包含匹配文本的所有行。
-w 只显示全字符合的列。
-x 只显示全列符合的列。
-y 此参数效果跟“-i”相同。
-o #只输出文件中匹配到的部分。
grep执行步骤
- (1) 把下一输入行复制到模式空间中. 模式空间是只可保存一个文本行的缓冲区.
- (2) 对模式空间应用正则表达式.
(3) 如果有匹配存在,该行从模式空间中被复制到标准输出.
grep实用程序对输入的每行重复这三个操作步骤.
注意特殊情形!!
- 1 . grep是一个搜索程序,它只能搜索匹配一个正则表达式的一行的存在性.
- 2 . grep可以对一行采取唯一的动作是把它发送到标准输出. 如果该行不匹配正则表达式,则其不被打印.
- 3 . 行的选择只基于正则表达式. 行编号或其他准则不能用于选择行.
- 4 . grep是一个过滤器. 它可用在管道的左边或右边.
- 5 . grep不能用于增加,删除或修改行.
- 6 . grep不能用于只打印行的一部分.
- 7 . grep不能只读取文件的一部分.
- 8 . grep不能基于前面的内容或下一行来选择一行.只有一个缓冲区,它只保存当前行.
grep pattern file
grep "pattern" file
#在file文件中查找包含"pattern"的文本行
jianliu@ubuntu:~/aa$ cat test0.txt
pattern
pattern1
padf
pattern 1
pattfs 2
jianliu@ubuntu:~/aa$ grep pattern test0.txt
pattern
pattern1
pattern 1
jianliu@ubuntu:~/aa$ grep "pattern" test0.txt
pattern
pattern1
pattern 1
jianliu@ubuntu:~$ echo -e "this is a word \nnext line" | grep word
this is a word
grep "math_word" file1 file2 file3
grep "match_word" *.doc #在所有.doc文件中查找
grep "match_word" * #在所有目录及文件中查找
grep match_word file --color=auto
jianliu@ubuntu:~$ cat test0.txt
word1
aword2
word3
1word4
word@
wor3
wo3
word12
#以匹配串结尾
jianliu@ubuntu:~$ grep -E '[a-z]{3,4}[0-9]$' test0.txt
word1
aword2
word3
1word4
wor3
#!!!!!注意!!!!----------------------
# 注意两种写法的区别
// (1) grep -E pattern 则后面的正则表达式不需要转义处理!!
// (2)grep pattern 后面的正则表达式需要进行转义处理!!
jianliu@ubuntu:~$ more test0.txt | grep '[a-z]\{3,4\}[0-9]$'
word1
aword2
word3
1word4
wor3
#只要包含匹配串
jianliu@ubuntu:~$ grep -E '[a-z]{3,4}[0-9]' test0.txt
word1
aword2
word3
1word4
wor3
word12
#以匹配串开头
jianliu@ubuntu:~$ grep -E '^[a-z]{3,4}[0-9]' test0.txt
word1
word3
wor3
word12
##---注意事项!!!
- #!!!!!注意!!!!———————-
- # 注意两种写法的区别
- (1) grep -E pattern 则后面的正则表达式不需要转义处理!!
- (2) grep pattern 后面的正则表达式需要进行转义处理!!
- 正则表达式的grep命令——egrep
jianliu@ubuntu:~$ egrep '[a-z]{3,4}[0-9]$' test0.txt
word1
aword2
word3
1word4
wor3
jianliu@ubuntu:~$ echo this is a line | grep -o line
line
$ grep -v match_pattern file
选项-v可以将匹配结果进行反转(invert)。
jianliu@ubuntu:~$ cat test0.txt
word1
aword2
word3
1word4
word@
wor3
wo3
word12
abcde
wore21
12345
jianliu@ubuntu:~$ grep -v 'word' test0.txt
wor3
wo3
abcde
wore21
12345
jianliu@ubuntu:~$ grep -c 'word' test0.txt
6
//需要注意的是-c只是统计匹配行的数量,并不是匹配的次数。例如:
jianliu@ubuntu:~$ echo -e "1 2 3 4\nhello\n5 6 7" | grep -c "[0-9]"
2
//尽管有6个匹配项,但命令只打印出2,这是因为只有两个匹配行。在单行中出现的多次匹配只被统计为一次。
jianliu@ubuntu:~$ echo -e "1 2 3 4\nhello\n5 6 7" | grep -o "[0-9]" | wc -l
7
$ cat sample1.txt
gnu is not unix
linux is fun
bash is art
$ cat sample2.txt
planetlinux
$ grep linux -n sample1.txt
2:linux is fun
$ cat sample1.txt | grep -n linux
2:linux is fun
$ grep linux -n sample1.txt sample2.txt
sample1.txt:2:linux is fun
sample2.txt:2:planetlinux
jianliu@ubuntu:~$ echo gnu is not unix | grep -b -o "not"
7:not
//一行中字符串的字符偏移是从该行的第一个字符开始计算,起始值是0。在上面的
//例子中, "not"的偏移值是7(也就是说, not是从该行的第7个字符开始的,即“ gnu is not unix”这一行)。
$ grep -l linux sample1.txt sample2.txt
sample1.txt
sample2.txt
- $ grep “pattern” [path] -R -n
- 命令中的path指定了搜索目录。
jianliu@ubuntu:~$ grep "//jianliu" . -r -n
./aa/a1.c:5: //jianliu
./hello.c:7: //jianliu
# . 表示当前目录,即/bin/home/jianliu
jianliu@ubuntu:~$ echo -e "hello\nword" | grep -i "HELLo"
hello
jianliu@ubuntu:~$ echo this is a line of text | grep -e "this" -e "line" -o
this
line
jianliu@ubuntu:~$ cat pat_file
hello
cool
jianliu@ubuntu:~$ echo hello this is cool | grep -f pat_file
hello this is cool
grep可以在搜索过程中指定(include)或排除(exclude)某些文件。我们通过通配符来指
定所include文件或exclude文件。
目录中递归搜索所有的 .c和 .cpp文件:
$ grep "main()" . -r --include *.c{c,cpp} #注意,some{str1,str2,str3}会扩展成somestr1,somestr2,somestr3。
在搜索中排除所有的readme文件:
$ grep "main()" . -r --exclude "readme"
- 需要排除目录,可使用–exclude-dir选项。
- 需要从文件中读取所需要排除的文件列表,使用–exclude-from FILE。
$ echo "test" > file1
$ echo "cool" > file2
$ echo "test" > file3
$ grep "test" file* -lZ | xargs -0 rm
# -Z通常和-l结合使用
在静默模式中, grep命令不会输出任何内容。它仅是运行命令,然后根据命令执行成功与否返回退出状态。
如果命令运行成功会返回0,如果失败则返回非0值。
//脚本: 利用grep的静默模式来测试文本匹配是否存在于某个文件中
jianliu@ubuntu:~/aa$ cat test0.sh
#!/bin/bash
#yong tu: ce shi wen jian shi fou bao han te ding de wen ben nei rong
if [ $# -ne 2 ]
then
echo "usage: $0 match_text filename"
exit 1
fi
match_text=$1
filename=$2
grep -q -E "$match_text" $filename
if [ $? -eq 0 ]
then
echo -e "Yes\nthe text [$match_text] exists in the file [$filename]"
else
echo -e "No\ntext [$match_text] does not exists in the file [$filename]"
fi
#---------------------------------------------------------------
jianliu@ubuntu:~/aa$ ./test0.sh [a-z]{3}[0-9] student_data.txt
Yes
the text [[a-z]{3}[0-9]] exists in the file [student_data.txt]
jianliu@ubuntu:~/aa$ ./test0.sh bob1 student_data.txt
Yes
the text [bob1] exists in the file [student_data.txt]
# -A 要打印匹配某个结果之后的3行
$ seq 10 | grep 5 -A 3
5
6
7
8
# -B 要打印匹配某个结果之前的3行
$ seq 10 | grep 5 -B 3
2
3
4
5
# -C 要打印匹配某个结果之前以及之后的3行
$ seq 10 | grep 5 -C 3
2
3
4
5
6
7
8
# -- 有多个匹配,使用--作为各部分之间的定界符
$ echo -e "a\nb\na\nb\nc" | grep a -A 1
a
b
--
a
b