![如何 grep 包含控制字符的联机帮助页中的标题](https://linux22.com/image/77726/%E5%A6%82%E4%BD%95%20grep%20%E5%8C%85%E5%90%AB%E6%8E%A7%E5%88%B6%E5%AD%97%E7%AC%A6%E7%9A%84%E8%81%94%E6%9C%BA%E5%B8%AE%E5%8A%A9%E9%A1%B5%E4%B8%AD%E7%9A%84%E6%A0%87%E9%A2%98.png)
我有一个联机帮助页,我想在特定部分找到一些内容。 Grep 遇到了困难,我发现问题是标题中包含控制字符,例如
SEE ALSO
是真的:
S^HSE^HEE^HE A^HAL^HLS^HSO^HO$
(谢谢,cat -e
今天也学到了)
一直在使用 grep 和 sed 的许多变体,使用字符类和其他技术,但一直无法解决它。
有什么建议如何最好地返回,比如“另请参阅部分中的所有内容”?这应该足够通用,对其他人有用,但又足够具体,可以提供详细的答案。 :)
请注意,我实际上并不需要 的帮助man
,因为在这种情况下,输出是由另一个命令生成的,例如aws help
通过管道传递到 less。
答案1
如何获取普通版本的手册页的想法可以在以下位置找到man man
:
man foo | col -b
基于此,您只能获得一个部分,例如pcregrep
:
man man | col -b | pcregrep -Mo '^SEE ALSO(.|\n)*?^[^ ]'
您可以对其进行一点调整,然后将其应用到函数g
中以轻松地代表s
任何部分的任何部分man
:
gsman () { man $1 | col -b | pcregrep -iMo "^$2(.|\n)*?(?=\n[A-Z])" ; }
和用法将是
gsman grep options | grep invert
答案2
六角转储器 ( hexdump
, xxd
)ascii(7)
可能在这里有用:
man ls | hexdump -C
...
这表明:
000045f0 35 29 2e 0a 0a 53 08 53 45 08 45 45 08 45 20 41 |5)...S.SE.EE.E A|
00004600 08 41 4c 08 4c 53 08 53 4f 08 4f 0a 20 20 20 20 |.AL.LS.SO.O. |
这就是十六进制代码 8,或者一堆bs
(这也是^H
显示的cat
意思)。至于如何剥离bs
,有多种方法:
% man ls | perl -ple 'tr/\x08//d' | grep SEE
SSEEEE AALLSSOO
好吧,这不好,还必须摆脱向后间隔的角色:
% man ls | perl -ple 's/.\x08//g' | perl -00 -nle 'print if m/SEE ALSO/'
SEE ALSO
chflags(1), chmod(1), sort(1), xterm(1), compat(5), termcap(5),
symlink(7), sticky(8)
答案3
section="SEE ALSO"
regex=$(sed 's/./&.*/g' <<<"$section") # S.*E.*E.* .*A.*L.*S.*O.*
# then
some help command | sed -n '/^'"$regex"'/,/^[^[:blank:]]/ p' | sed '$d'
- 正则表达式允许给定节名称的每个字母之间有任意数量的字符。
- 第一个 sed 命令仅输出给定部分正则表达式和下一部分之间的行(我假设该部分中的所有行都有前导空格)
- 第二个 sed 命令删除尾随部分标题。
作为 bash 函数:
man_section() {
local section=$1
local regex=$(sed 's/./&.*/g' <<<"$section")
sed -n '/^'"$regex"'/,/^[^[:blank:]]/ p' | sed '$d'
}
some help command | man_section "SEE ALSO"