Skip to content

grep命令

1、简介

grep是Linux中最常用的”文本处理工具”之一,grep与sed、awk合称为Linux中的三剑客。 grep的全称为: Global search Regular Expression and Print out the line 全称中的”Global search”为全局搜索之意。 全称中的”Regular Expression”表示正则表达式。 所以,从grep的全称中可以了解到,grep是一个可以利用”正则表达式”进行”全局搜索”的工具

2、常用用法

grep -rin 字符串 目标区域 (在目标区域内的文件内容中查找) grep --color 可以为查找的内容加颜色 通常修改alias。

3、帮助

[root@ubuntu0006:/media/hankin/vdb/app] #grep --help
用法: grep [选项]... PATTERN [FILE]...
在每个 FILE 或是标准输入中查找 PATTERN。
默认的 PATTERN 是一个基本正则表达式(缩写为 BRE)。
例如: grep -i 'hello world' menu.h main.c

正则表达式选择与解释:
  -E, --extended-regexp     PATTERN 是一个可扩展的正则表达式(缩写为 ERE)
  -F, --fixed-strings       PATTERN 是一组由断行符分隔的字符串。
  -G, --basic-regexp        PATTERN 是一个基本正则表达式(缩写为 BRE)
  -P, --perl-regexp         PATTERN 是一个 Perl 正则表达式
  -e, --regexp=PATTERN      用 PATTERN 来进行匹配操作
  -f, --file=FILE           从 FILE 中取得 PATTERN
  -i, --ignore-case         忽略大小写
  -w, --word-regexp         强制 PATTERN 仅完全匹配字词
  -x, --line-regexp         强制 PATTERN 仅完全匹配一行
  -z, --null-data           一个 0 字节的数据行,但不是空行

杂项:
  -s, --no-messages         不显示错误信息
  -v, --invert-match        选中不匹配的行
  -V, --version             显示版本信息并退出
      --help                显示此帮助并退出

输出控制:
  -m, --max-count=NUM       NUM 次匹配后停止
  -b, --byte-offset         输出的同时打印字节偏移
  -n, --line-number         输出的同时打印行号
      --line-buffered       每行输出清空
  -H, --with-filename       为每一匹配项打印文件名
  -h, --no-filename         输出时不显示文件名前缀
      --label=LABEL         将LABEL 作为标准输入文件名前缀
  -o, --only-matching       只显示匹配PATTERN 部分的行
  -q, --quiet, --silent     不显示所有常规输出
      --binary-files=TYPE   设定二进制文件的TYPE 类型;
                            TYPE 可以是`binary', `text', 或`without-match'
  -a, --text                等同于 --binary-files=text
  -I                        等同于 --binary-files=without-match
  -d, --directories=ACTION  读取目录的方式;
                            ACTION 可以是`read', `recurse',或`skip'
  -D, --devices=ACTION      读取设备、先入先出队列、套接字的方式;
                            ACTION 可以是`read'或`skip'
  -r, --recursive           等同于--directories=recurse
  -R, --dereference-recursive       同上,但遍历所有符号链接
      --include=FILE_PATTERN  只查找匹配FILE_PATTERN 的文件
      --exclude=FILE_PATTERN  跳过匹配FILE_PATTERN 的文件和目录
      --exclude-from=FILE   跳过所有除FILE 以外的文件
      --exclude-dir=PATTERN  跳过所有匹配PATTERN 的目录。
  -L, --files-without-match  只打印不匹配FILEs 的文件名
  -l, --files-with-matches  只打印匹配FILES 的文件名
  -c, --count               只打印每个FILE 中的匹配行数目
  -T, --initial-tab         行首tabs 分隔(如有必要)
  -Z, --null                在FILE 文件最后打印空字符

文件控制:
  -B, --before-context=NUM  打印文本及其前面NUM 行
  -A, --after-context=NUM   打印文本及其后面NUM 行
  -C, --context=NUM         打印NUM 行输出文本
  -NUM                      等同于 --context=NUM
      --color[=WHEN],
      --colour[=WHEN]       使用标记高亮匹配字串;
                            WHEN 可以是`always', `never'或`auto'
  -U, --binary              不要清除行尾的CR 字符(MSDOS/Windows)
  -u, --unix-byte-offsets   忽略CR 字符,报告字节偏移
                             (MSDOS/Windows)

'egrep' 即'grep -E'。'fgrep' 即'grep -F'。
直接调用'egrep' 或是'fgrep' 均已被废弃。
若FILE 为 -,将读取标准输入。不带FILE,读取当前目录,除非命令行中指定了-r 选项。
如果少于两个FILE 参数,就要默认使用-h 参数。
如果有任意行被匹配,那退出状态为 0,否则为 1;
如果有错误产生,且未指定 -q 参数,那退出状态为 2。

4、搜索显示前后多行

at xxx.log | grep -A 10 ERROR 后10行 cat xxx.log | grep -B 10 ERROR 前10行 cat xxx.log | grep -C 30 ERROR 前后各30行 经常用 迅速定位ERROR上下文

grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行 grep -B 5 foo file 显示foo及前5行 grep -A 5 foo file 显示foo及后5行

5、字符串全匹配

模糊匹配 $ grep "abc" # 结果为abcd, abcde, abc等 全匹配 $ grep -Rw "abc" # 结果为abc

6、grep时显示"匹配到二进制文件"

6-1、原因

grep如果碰到\000 NUL字符,就会认为文件是二进制文件,而 grep 匹配 默认忽略二进制数据。 我发现是匹配的那一行出现了中文,并且中文格式还有些问题,删除中文后grep正常。。。。。。。。。。。。。

所以要使用grep -a属性:不忽略二进制的数据。 grep的-a或--text参数功能:将 binary 文件以 text 文件的方式搜寻数据

6-2、解决

grep -a file_name grep --text file_name

grep时提示:Binary file (standard input) matches grep只递归匹配文本文件,不匹配二进制文件中的内容 grep get_default_error_string /* -rFn --binary-files=without-match 增加--binary-files=without-match参数即可。

6-3、进一步思考

rk1314_64bit:/proc # grep -R "null pointer" / 2>/dev/null
Binary file /vendor/lib/modules/wifi/8822be.ko matches
Binary file /vendor/lib/modules/wifi/8821cu.ko matches
Binary file /vendor/lib/modules/wifi/bcmdhd.ko matches

rk1314_64bit:/proc # grep -aR "null pointer" / 2>/dev/null
/vendor/lib/modules/wifi/8822be.ko:null pointer!!
/vendor/lib/modules/wifi/8821cu.ko:[ERR]null pointer
/vendor/lib/modules/wifi/bcmdhd.ko:%s : bus is null pointer , exit

所以说不添加a参数还是最好的,最好是过滤掉二进制内容显示。

7、使用grep搜索多个字符串

三种方法:

  • 转义字符\
  • grep -E (-E, --extended-regexp PATTERN 是一个可扩展的正则表达式(缩写为 ERE))
  • egrep
[root@ubuntu0006:/media/hankin/vdb/log/shell] #grep 'ltest' log.sh
[root@ubuntu0006:/media/hankin/vdb/log/shell] #grep 'ltext' log.sh
ltext()
                ltext -n '.';
        ltext "${CBOLD}[T]${CLOG_PRE_WAPPER}${C0}$*";
export -f ltext
[root@ubuntu0006:/media/hankin/vdb/log/shell] #grep 'ltest|ltext' log.sh
[root@ubuntu0006:/media/hankin/vdb/log/shell] #grep 'ltest\|ltext' log.sh
ltext()
                ltext -n '.';
        ltext "${CBOLD}[T]${CLOG_PRE_WAPPER}${C0}$*";
export -f ltext
[root@ubuntu0006:/media/hankin/vdb/log/shell] #grep -E 'ltest|ltext' log.sh
ltext()
                ltext -n '.';
        ltext "${CBOLD}[T]${CLOG_PRE_WAPPER}${C0}$*";
export -f ltext
[root@ubuntu0006:/media/hankin/vdb/log/shell] #egrep 'ltest|ltext' log.sh
ltext()
                ltext -n '.';
        ltext "${CBOLD}[T]${CLOG_PRE_WAPPER}${C0}$*";
export -f ltext

root@hankin:/var/lock# cat /sys/kernel/debug/usb/usbmon/3u | grep "Ci\|Co"
root@hankin:/var/lock# cat /sys/kernel/debug/usb/usbmon/3u | grep -E "Ci|Co"
root@hankin:/var/lock# cat /sys/kernel/debug/usb/usbmon/3u | egrep "Ci|Co"

亲测上面三种方式在xubuntu系统里面有效,但是在安卓8.1.0系统里面只有grep -E生效,其他方式行不通。但是发现egrep命令前面加入busybox命令也行得通,而grep "Ci|Co"始终行不通。

注意:.一定需要使用\转义字符,而|没有-E参数则需要使用\转义字符,有-E则不需要。

root@292d069d5401  ~/code/src(person-TD2024123000056)
# git status . -uno | grep ".cpp$|.h$"

root@292d069d5401  ~/code/src(person-TD2024123000056)
# git status . -uno | grep ".cpp$\|.h$"
        修改:     client/X11/client_msg.cpp
        修改:     client/X11/client_msg.h
        修改:     usbredir-0.7/install-sh

root@292d069d5401  ~/code/src(person-TD2024123000056)
# git status . -uno | grep -E ".cpp$|.h$"
        修改:     client/X11/client_msg.cpp
        修改:     client/X11/client_msg.h
        修改:     usbredir-0.7/install-sh

root@292d069d5401  ~/code/src(person-TD2024123000056)
# git status . -uno | grep -E ".cpp$|\.h$"
        修改:     client/X11/client_msg.cpp
        修改:     client/X11/client_msg.h

8、q参数

注意:直接在终端执行不会有任何返回值,不要以为没有找到相关内容。

root@hankin:/usr/local/bin# grep -q root /proc/version
root@hankin:/usr/local/bin# echo $?
0
root@hankin:/usr/local/bin# grep -q rootj /proc/version
root@hankin:/usr/local/bin# echo $?
1

grep -q用于if逻辑判断。

突然发现grep -q 用于if逻辑判断很好用。

-q 参数,本意是 Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. 中文意思为,安静模式,不打印任何标准输出。如果有匹配的内容则立即返回状态值0。

test.sh:

#!/bin/bash

if grep -q hello data.txt ; then
    echo "data.txt has word 'hello'"
else
    echo "data.txt has not word 'hello'"
fi

if grep -q world data.txt; then
    echo "data.txt has word 'world'"
else
    echo "data.txt has not word 'world'"
fi

success=0
if echo ${success} ; then
    echo yes
else
    echo no
fi

data.txt:

nihao
nihaooo
hello

运行结果:

data.txt has word 'hello'
data.txt has not word 'world'
0
yes

9、grep的-r和-R参数区别

[root@ubuntu0006:/media/hankin/vdb/study/grep_rR] #ll
总用量 16
drwxr-xr-x  2 root root 4096 12月 24 10:08 ./
drwxr-xr-x 44 root root 4096 5月  11 15:32 ../
-rw-r--r--  1 root root    5 12月 24 10:06 a
lrwxrwxrwx  1 root root    1 12月 24 10:07 b -> a
-rw-r--r--  1 root root   57 12月 24 10:08 README.md
[root@ubuntu0006:/media/hankin/vdb/study/grep_rR] #grep ping    (会卡住)
^C
[root@ubuntu0006:/media/hankin/vdb/study/grep_rR] #grep -r ping
a:ping
README.md:grep -R ping
README.md:grep -r ping
[root@ubuntu0006:/media/hankin/vdb/study/grep_rR] #grep -R ping
a:ping
README.md:grep -R ping
README.md:grep -r ping
b:ping
[root@ubuntu0006:/media/hankin/vdb/study/grep_rR] #grep -r ping b
ping

-r,--recursive 遍历每个目录下的所有文件,递归,不包含符号链接,只有当他们是在命令行上。这相当于 -d递归选项。

-R,--dereference递归 遍历所有文件的每个目录下,递归。 包含所有符号链接,不像-r。

10、grep的规则表达式

\ 反义字符:如"\"\""表示匹配""
[ - ] 匹配一个范围,[0-9a-zA-Z]匹配所有数字和字母
* 所有字符,长度可为0
+ 前面的字符出现了一次或者多次
^ #匹配行的开始 如:'^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。

[root@ubuntu0006:/home] #cat test.txt
a g r e
u c j alike
i x k like
a f g liker
a f h g liker
s g e g
[root@ubuntu0006:/home] #grep "^a" test.txt             (查找以a开头的行)
a g r e
a f g liker
a f h g liker
[root@ubuntu0006:/home] #grep "^a.*r$" test.txt         (同时查找以a开头同时以r结尾的行)
a f g liker
a f h g liker
[root@ubuntu0006:/home] #grep "^a.*h.*r$" test.txt      (同时查找以a开头,包含字符h,并以r结尾的行)
a f h g liker
[root@ubuntu0006:/home] #grep "^a\|e$" test.txt         (提取以a开头,或者以e结尾的行)
a g r e
u c j alike
i x k like
a f g liker
a f h g liker

10-1、*符号的实战

错误演示,也是问题来源:

[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep 829
collection-patches-20240829
collection-patches-20240829
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep "*829"
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep *829
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep '*829'
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep '829'
collection-patches-20240829
collection-patches-20240829
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep 'patches'
collection-patches-20240710
collection-patches-20240829
collection-patches-20240829
collection-patches-20240928(20240929)
collection-patches-20240821
collection-patches-20240821
collection-patches-20240821
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep '829$'
collection-patches-20240829
collection-patches-20240829
[root@ubuntu0006:/media] ((550cf74...)) #git tag | grep 'patches$'
[root@ubuntu0006:/media] ((550cf74...)) #

正确的方式:

[root@ubuntu0006:~] #grep " *short" te.c
        unsigned short vid = desc.idVendor;
        unsigned short pid = desc.idProduct;
            unsigned short vid = desc.idVendor;
            unsigned short pid = desc.idProduct;
[root@ubuntu0006:~] #cat te.c | grep ' *short'
        unsigned short vid = desc.idVendor;
        unsigned short pid = desc.idProduct;
            unsigned short vid = desc.idVendor;
            unsigned short pid = desc.idProduct;
[root@ubuntu0006:~] #cat te.c | grep driver
* 文 件 名: replace_kernel_driver.c
            op_attach_kernel_driver(fd, 0);
            op_attach_kernel_driver(fd, 1);
            op_detach_kernel_driver(fd, 0);
            op_detach_kernel_driver(fd, 1);
            detach_kernel_driver_and_claim(fd, 0);
            detach_kernel_driver_and_claim(fd, 1);
[root@ubuntu0006:~] #cat te.c | grep *driver
[root@ubuntu0006:~] #cat te.c | grep  *driver
[root@ubuntu0006:~] #cat te.c | grep *short
[root@ubuntu0006:~] #cat te.c | grep  *short
[root@ubuntu0006:~] #cat te.c | grep   *short
[root@ubuntu0006:~] #cat te.c | grep  .*driver
* 文 件 名: replace_kernel_driver.c
            op_attach_kernel_driver(fd, 0);
            op_attach_kernel_driver(fd, 1);
            op_detach_kernel_driver(fd, 0);
            op_detach_kernel_driver(fd, 1);
            detach_kernel_driver_and_claim(fd, 0);
            detach_kernel_driver_and_claim(fd, 1);
[root@ubuntu0006:~] #cat te.c | grep  driver*
* 文 件 名: replace_kernel_driver.c
            op_attach_kernel_driver(fd, 0);
            op_attach_kernel_driver(fd, 1);
            op_detach_kernel_driver(fd, 0);
            op_detach_kernel_driver(fd, 1);
            detach_kernel_driver_and_claim(fd, 0);
            detach_kernel_driver_and_claim(fd, 1);
[root@ubuntu0006:~] #cat te.c | grep  driver.
* 文 件 名: replace_kernel_driver.c
            op_attach_kernel_driver(fd, 0);
            op_attach_kernel_driver(fd, 1);
            op_detach_kernel_driver(fd, 0);
            op_detach_kernel_driver(fd, 1);
            detach_kernel_driver_and_claim(fd, 0);
            detach_kernel_driver_and_claim(fd, 1);
[root@ubuntu0006:~] #cat te.c | grep  driver***
* 文 件 名: replace_kernel_driver.c
            op_attach_kernel_driver(fd, 0);
            op_attach_kernel_driver(fd, 1);
            op_detach_kernel_driver(fd, 0);
            op_detach_kernel_driver(fd, 1);
            detach_kernel_driver_and_claim(fd, 0);
            detach_kernel_driver_and_claim(fd, 1);

总结:使用grep命令一般是不需要使用到通配符*,使用了你就错了!!! 另外注意git branch和git tag显示出来的结果不一样额。 使用grep命令时*符号不能单独匹配使用,需要结合其他符号进行组合,另外grep命令不需要像find命令那样需要*去通配,如:

[root@ubuntu0006:~] #find . -maxdepth 1 -name *c
find: 路径必须在表达式之前: k.c
用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec|time] [path...] [expression]
[root@ubuntu0006:~] #find . -maxdepth 1 -name "*c"
./.xsm7l5yUc
./.dmrc
./Public
./te.c
./.bashrc
./exec_shell_cmd_return_result.c
./Music
./k.c
./.vnc
./malloc_deallocated_with_delete.c
[root@ubuntu0006:~] #find . -maxdepth 1 -name "c"
[root@ubuntu0006:~] #

11、grep统计文件个数

  1. 查看某文件夹下文件的个数:
# ls -l |grep "^-"|wc -l    or    # find ./dir -type f | wc -l
  1. 查看某文件夹下文件的个数,包括子文件夹里的:
# ls -lR | grep "^-" | wc -l
  1. 查看某文件夹下文件夹的个数,包括子文件夹里的:
# ls -lR | grep "^d" | wc -l

12、grep出现大量的各种错误

rk1314_64bit:/proc # grep -R "null pointer" /
/system/bin/grep: /sys/bus/cpu/uevent: Permission denied
/system/bin/grep: /sys/bus/cpu/drivers_probe: Permission denied
/system/bin/grep: /sys/bus/i2c/devices/i2c-0/i2c-dev/i2c-0/power/autosuspend_delay_ms: I/O error
/system/bin/grep: warning: /sys/bus/i2c/devices/i2c-0/i2c-dev/i2c-0/device: recursive directory loop

解决方法:
rk1314_64bit:/proc # grep -R "null pointer" / 2>/dev/null

13、统计出现次数

o参数的重要性,注意126行出现了两个int也统计出来了。

[root@ubuntu0006:~/cmake] #grep -Rn "int" a.cpp
41:     * this bDeviceClass value indicates that each interface specifies its
126:int main(int argc, char *argv[])
129:    int r;
[root@ubuntu0006:~/cmake] #grep -Rno "int" a.cpp
41:int
126:int
126:int
129:int
[root@ubuntu0006:~/cmake] #grep -Rno "int" a.cpp | wc -l
4

14、转义字符

root@android:/ # cat /sys/kernel/debug/usb/usbmon/3u                                              <
d9219c80 756921660 C Ii:3:004:1 0:2 8 = 0000fc00 0000fcff
d9219c80 756921741 S Ii:3:004:1 -115:2 8 <
d9219c80 756923679 C Ii:3:004:1 0:2 8 = 0003fc00 0300fcff
d9219c80 756923855 S Ii:3:004:1 -115:2 8 <
d9219c80 756925658 C Ii:3:004:1 0:2 8 = 0002fa00 0200faff
d9219c80 756925750 S Ii:3:004:1 -115:2 8 <
d9219c80 756927659 C Ii:3:004:1 0:2 8 = 0004f900 0400f9ff
d9219c80 756927752 S Ii:3:004:1 -115:2 8 <
d9219c80 756929656 C Ii:3:004:1 0:2 8 = 0002f800 0200f8ff

root@android:/ # cat /sys/kernel/debug/usb/usbmon/3u | grep "\-115:2"
d9219c80 801365751 S Ii:3:004:1 -115:2 8 <
d9219c80 801367771 S Ii:3:004:1 -115:2 8 <
d9219c80 801369738 S Ii:3:004:1 -115:2 8 <
d9219c80 801371733 S Ii:3:004:1 -115:2 8 <
d9219c80 801383761 S Ii:3:004:1 -115:2 8 <
d9219c80 801427738 S Ii:3:004:1 -115:2 8 <
d9219c80 801431749 S Ii:3:004:1 -115:2 8 <
d9219c80 801435742 S Ii:3:004:1 -115:2 8 <

root@android:/ # cat /sys/kernel/debug/usb/usbmon/3u | grep "2 8"
d9219c80 814335664 C Ii:3:004:1 0:2 8 = 00010000 01000000
d9219c80 814335769 S Ii:3:004:1 -115:2 8 <
d9219c80 814337665 C Ii:3:004:1 0:2 8 = 0001ff00 0100ffff
d9219c80 814337751 S Ii:3:004:1 -115:2 8 <
d9219c80 814339658 C Ii:3:004:1 0:2 8 = 00010000 01000000
d9219c80 814339718 S Ii:3:004:1 -115:2 8 <
d9219c80 814341660 C Ii:3:004:1 0:2 8 = 00010000 01000000
d9219c80 814341726 S Ii:3:004:1 -115:2 8 <
d9219c80 814343658 C Ii:3:004:1 0:2 8 = 0001ff00 0100ffff
d9219c80 814343737 S Ii:3:004:1 -115:2 8 <

15、将grep过滤的内容输出到文件中

15-1、需求

统计某个进程一段时间的CPU使用率数据,并将结果输出到文件保存。

top -b -d 1 -p 1234 | grep 1234

15-2、解决方案

咋一看,似乎是一个很简单的问题,就是 taif -f | grep 过滤出来的内容重定向到文件中就行了,但是为什么文件一直为空呢?

其实这要从shell的输出机制说起,因为标准输出到终端时默认行缓冲或无缓冲,重定向到硬盘之后,就变成了全缓冲。

因此 tail -f 往终端打印,和往文件中写是不一样的,往文件中写,需要先写到pipe的缓冲区中, 然后再写到文件中。tail -f 之后表示一个流还没有完成, 缓冲区不会自动写,因此导致内容无法写入文件。

解决方法呢?很简单,既然缓冲区不自动写,那我们就强制写。方法不止一种,此处我们单讲 fflush: fflush是一个在C语言标准输入输出库中的函数,功能是冲洗流中的信息,该函数通常用于处理磁盘文件。fflush()会强迫将缓冲区内的数据写回参数stream 指定的文件中。

以上是百度百科中对fflush释义,在shell中,我们可以使用awk来调用fflush,话不多说,先上shell:

tail -f xxx.log | awk '/china|beijing/ {print $0; fflush() }' >> out.txt

此命令即实现实时过滤 xxx.log 文件中的关键词 china 或 beijing ,并将对应的行输出到out.txt文件中。

[root@ubuntu0006:~] #top -b -d 1 -p 1956 | grep 1956 >> out.txt
^C
[root@ubuntu0006:~] #cat out.txt
[root@ubuntu0006:~] #
[root@ubuntu0006:~] #top -b -d 1 -p 1956 | awk '/1956/ {print $0}' >> out.txt
^C
[root@ubuntu0006:~] #cat out.txt
[root@ubuntu0006:~] #
[root@ubuntu0006:~] #top -b -d 1 -p 1956 | awk '/1956/ {print $0; fflush() }' >> out.txt
^C
[root@ubuntu0006:~] #cat out.txt
 1956 root      20   0  924764  21596  14088 S   0.0  0.3 122:42.61 ToolsAPI
 1956 root      20   0  924764  21472  14088 S   1.0  0.3 122:42.62 ToolsAPI
 1956 root      20   0  924764  21472  14088 S   1.0  0.3 122:42.63 ToolsAPI
 1956 root      20   0  924764  21472  14088 S   0.0  0.3 122:42.63 ToolsAPI
 1956 root      20   0  924764  21472  14088 S   0.0  0.3 122:42.63 ToolsAPI
 1956 root      20   0  924764  21472  14088 S   0.0  0.3 122:42.63 ToolsAPI

16、cat命令查看日志使用grep命令搜索关键字不全

[root@ubuntu0006:/var/log] #cat syslog  | grep 21514
Nov  9 11:36:06 ubuntu0006 kernel: [    2.215148] uhci_hcd 0000:00:19.2: UHCI Host Controller
匹配到二进制文件 (标准输入)

[root@ubuntu0006:/var/log] #cat syslog  | grep -a 21514
Nov  9 11:36:06 ubuntu0006 kernel: [    2.215148] uhci_hcd 0000:00:19.2: UHCI Host Controller
Mar 19 04:17:01 ubuntu0006 CRON[21514]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)

[root@ubuntu0006:/var/log] #cat syslog  | grep --text 21514
Nov  9 11:36:06 ubuntu0006 kernel: [    2.215148] uhci_hcd 0000:00:19.2: UHCI Host Controller
Mar 19 04:17:01 ubuntu0006 CRON[21514]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)

[root@ubuntu0006:/var/log] #cat syslog  | grep --binary-files=text 21514
Nov  9 11:36:06 ubuntu0006 kernel: [    2.215148] uhci_hcd 0000:00:19.2: UHCI Host Controller
Mar 19 04:17:01 ubuntu0006 CRON[21514]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)

[root@ubuntu0006:/var/log] #strings syslog | grep 21514
Nov  9 11:36:06 ubuntu0006 kernel: [    2.215148] uhci_hcd 0000:00:19.2: UHCI Host Controller
Mar 19 04:17:01 ubuntu0006 CRON[21514]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)

16-1、问题原因

当 grep 显示“匹配到二进制文件(标准输入)”时,这意味着 grep 检测到输入数据包含二进制内容,而不是纯文本。默认情况下,grep 在遇到二进制数据时会停止处理并显示此消息。

16-2、解决方案

  • 使用 -a 或 --text 选项来强制 grep 将文件视为文本文件,即使它包含二进制数据。这可以让 grep 继续处理文件中的文本部分。
  • 不需要处理二进制内容,可以使用 --binary-files=text 选项,这与 -a 类似。
  • 如果文件确实包含二进制数据,但你只关心其中的文本部分,可以使用 strings 命令提取文本,然后再用 grep 搜索

16-3、检查文件是否含有二进制内容

放弃,没有找到答案:

hj文件含有中文,jh不含有中文:
[root@ubuntu0006:~] #hexdump -C hj
00000000  31 32 33 0a 31 32 0a 39  38 e4 bd 95 e5 81 a5 31  |123.12.98......1|
00000010  32 0a 6a 6b 0a 31 32 0a  e6 8b 89 e6 8b 89 0a 31  |2.jk.12........1|
00000020  32 0a 31 32 0a                                    |2.12.|
00000025
[root@ubuntu0006:~] #hexdump -C jh
00000000  31 32 33 0a 31 32 0a 39  38 31 32 0a 6a 6b 0a 31  |123.12.9812.jk.1|
00000010  32 0a 0a 31 32 0a 31 32  0a                       |2..12.12.|
00000019
[root@ubuntu0006:~] #xxd hj
00000000: 3132 330a 3132 0a39 38e4 bd95 e581 a531  123.12.98......1
00000010: 320a 6a6b 0a31 320a e68b 89e6 8b89 0a31  2.jk.12........1
00000020: 320a 3132 0a                             2.12.
[root@ubuntu0006:~] #xxd jh
00000000: 3132 330a 3132 0a39 3831 320a 6a6b 0a31  123.12.9812.jk.1
00000010: 320a 0a31 320a 3132 0a                   2..12.12.
[root@ubuntu0006:~] #od -c hj
0000000   1   2   3  \n   1   2  \n   9   8 344 275 225 345 201 245   1
0000020   2  \n   j   k  \n   1   2  \n 346 213 211 346 213 211  \n   1
0000040   2  \n   1   2  \n
0000045
[root@ubuntu0006:~] #od -c jh
0000000   1   2   3  \n   1   2  \n   9   8   1   2  \n   j   k  \n   1
0000020   2  \n  \n   1   2  \n   1   2  \n
0000031

自己创建的文件并没有复现问题:
[root@ubuntu0006:~] #grep '12' hj
123
12
98何健12
12
12
12
[root@ubuntu0006:~] #grep -P '[^\x20-\x7E\t\r\n]' hj
98何健12
拉拉
[root@ubuntu0006:~] #cat hj | grep 12
123
12
98何健12
12
12
12

This website is released under the MIT License.