Bash 为什么将同一手册页变灰有时会导致错误?

Bash 为什么将同一手册页变灰有时会导致错误?,bash,shell,curl,grep,manpage,Bash,Shell,Curl,Grep,Manpage,完全相同的命令: man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' | grep ' 6 ' 有时给出预期输出: 6 Couldn't resolve host. The given remote host was not resolved. 有时会出现错误: Binary file (standard input) matches 例如: 相关软件包的版本: $ lsb_release -a No LSB modu

完全相同的命令:

man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' | grep '  6  '
有时给出预期输出:

       6      Couldn't resolve host. The given remote host was not resolved.
有时会出现错误:

Binary file (standard input) matches
例如:

相关软件包的版本:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:        16.04
Codename:       xenial

$ grep --version
grep (GNU grep) 2.25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

$ man --version
man 2.7.5

$ curl --version
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets
$lsb_发行版-a
没有可用的LSB模块。
分发服务器ID:Ubuntu
说明:Ubuntu 16.04.1 LTS
发行日期:16.04
代号:xenial
$grep--版本
grep(GNU grep)2.25
版权所有(C)2016免费软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本。
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。
由Mike Haertel和其他人撰写,请参见。
$man--版本
男子2.7.5
$curl--版本
curl 7.47.0(x86_64-pc-linux-gnu)libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
协议:dict文件ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smb smtp smtps telnet tftp
功能:AsynchDNS IDN IPv6大文件GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets
这件事真让我抓狂

我通过将
-a
标记放入我的greps中解决了我的问题,例如:
man curl | grep-Pzoa'退出代码(.|\n)*作者| grep-a'6'


但我真的很困惑,为什么它有时只会出错?..

因为使用了
-z
选项,第一个grep会在输出的末尾附加一个NUL字符。接下来会发生什么取决于缓冲的变幻莫测。如果第二个grep在分析文件之前看到NUL,它将决定该文件是二进制文件。如果没有,它会找到你想要的匹配项

所以,这恰好对我有用:

$ man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' | grep '  6  '
       6      Couldn't resolve host. The given remote host was not resolved.
但是,如果我将第一个grep的输出放在一个临时文件中,并要求第二个grep读取该文件,那么第二个grep总是会抱怨输入是二进制的:

$ man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' >tmpfile;  grep '  6  ' tmpfile
Binary file tmpfile matches
备选方案:使用awk 避免NUL字符问题以及减少所需进程数的一种方法是使用awk:

$ man curl | awk '/EXIT CODES/,/AUTHORS/{if (/   6   /) print}'
       6      Couldn't resolve host. The given remote host was not resolved.
备选方案:使用sed 备选方案:使用greps和tr 根据建议,另一个选项是使用
tr
以换行符替换NUL:

$ man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' | tr '\000' '\n' | grep '  6  '
       6      Couldn't resolve host. The given remote host was not resolved.

或者你可以把NUL变成一个新行,使用
tr
@tripleee非常好。非常感谢。我刚刚在答案中添加了
tr
方法。
$ man curl | sed -n '/EXIT CODES/,/AUTHORS/{/   6   /p}'
       6      Couldn't resolve host. The given remote host was not resolved.
$ man curl | grep -Pzo 'EXIT CODES(.|\n)*AUTHORS' | tr '\000' '\n' | grep '  6  '
       6      Couldn't resolve host. The given remote host was not resolved.