为什么man page标题上有两个 DATE(1)的追踪过程

简介: 为什么标题上有两个DATE(1) 的追踪过程

为什么标题上有两个DATE(1) 的追踪过程



我们通过

man -aw date

得到

/usr/share/man/man1/date.1.gz


用zcat观察

zcat /usr/share/man/man1/date.1.gz |less


可以看到第一行是

.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.3.
.TH DATE "1" "February 2017" "GNU coreutils 8.25" "User Commands"
.SH NAME
date \- print or set the system date and time
.SH SYNOPSIS
.B date
[\fI\,OPTION\/\fR]... [\fI\,+FORMAT\/\fR]
.br
.B date
......

这里 .TH DATE "1"便是DATE(1)的出处, 但为什两个呢? 继续挖


用grep过滤

zcat /usr/share/man/man1/date.1.gz | grep 'DATE \"1\"'

搜索仅有一行输出


9PFY4YQ%8_ZA_%]8Q~$VBQH.png


查找man源码


$ which man
/usr/bin/man
$ dpkg --search /usr/bin/man
man-db: /usr/bin/man
$ apt-get source man-db


狂看一天之后, 发现man-db用的是pipeline,格式化和最终的输出调用的都是外部指令

/* Return pipeline to format file to stdout. */
static pipeline *make_roff_command (const char *dir, const char *file,
                    pipeline *decomp, const char *dbfilters,
                    char **result_encoding)
......

从这个函数的内容里, 发现主要是调用的roff/nroff/troff/groff这一组格式化命令来完成的.


创建一个小文件a.txt,包含如下内容

.

TH MAN 7 2012-08-05 "Linux" "Linux Programmer's Manual"
.SH NAME
man \- macros to format man pages
用groff试下
$ groff -mandoc -T ascii a.txt
输出了以下内容
MAN(7)                     Linux Programmer's Manual                    MAN(7)
NAME
       man - macros to format man pages
Linux                             2012-08-05                            MAN(7)


果然是我想要的.


用strace查看调用过程

还是pipe调用....

下载groff源码

$ apt-get source groff


发现可以用-V参数查看pipeline命令

$ groff -V -mandoc -T ascii a.txt
troff -mandoc -Tascii a.txt | grotty


单独执行troff

troff -mandoc -Tascii a.txt

得到

x T ascii
x res 240 24 40
x init
p1
x X tty: sgr 0
x font 1 R
f1
s10
V40
H0
md
DFd
tMAN(7)
h504
tLinux
wh24
tProgrammer's
wh24
tManual
h480
tMAN(7)
......

从这里可以看到在a.txt里只出现一次的MAN(7)被输出了两次.


troff源码分析

troff 源码也在groff包里.

搜索源码并没有找到直接处理.TH标记的地方, 发现troff与man的宏有关.


troff与宏指令man macros

通过以下指令得到troff在运行过程中打开过的.tmac宏文件

$ strace troff -mandoc -Tascii ~/a.txt 2>&1 |grep -v such | grep tmac

输出如下

open("/usr/share/groff/1.22.3/tmac/troffrc", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/composite.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/fallbacks.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/tty.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/hyphen.us", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/hyphenex.us", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/papersize.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/pspic.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/andoc.tmac", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/troffrc-end", O_RDONLY) = 3
open("/usr/share/groff/1.22.3/tmac/an-old.tmac", O_RDONLY) = 4
open("/usr/share/groff/1.22.3/tmac/devtag.tmac", O_RDONLY) = 5
open("/usr/share/groff/1.22.3/tmac/an-ext.tmac", O_RDONLY) = 5
open("/usr/share/groff/site-tmac/man.local", O_RDONLY) = 5

在相应目录下只找到少处和.TH处理有关的片断

/usr/share/groff/1.22.3/tmac$ grep -w TH -R *
andoc.tmac:.  als TH reload-man
andoc.tmac:.  rm TH
andoc.tmac:\\*[TH]\\
andoc.tmac:.als TH reload-man
andoc.tmac:.\" dummy equation macros -- eqnrc is read before .TH or .Dd is parsed
an-old.tmac:.\" If you need to add things to TH, use `.am1 TH'.
an-old.tmac:.\" .TH title section extra1 extra2 extra3
an-old.tmac: TH

.tmac文件格式在这里有详细的介绍:

doc.tmac 主手册宏包mdoc.tmac 对 doc.tmac调用的封装mdoc/doc-common 共用字符串,定义,与印刷输出相关内容.mdoc/doc-nroff 用于 TTY设备输出的定义.mdoc/doc-ditroff 用于其它设备输出的定义mdoc.local 本地补充与客户化相关.andoc.tmac 如果你搞不清是该用 -mdoc 还是 -man 包时就用这个.


真相大白


最终在an-old.tmac层层定义的宏里找到了这行:

259 .de1 PT
260 .  tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
261 ..


编辑保存, 果然如此

.  tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]' [Eureka!] \\*[an-title](\\*[an-section])'


截图留念

_2$65%S}5C(@J5EKD50TO8Y.png

这里有man-db有相关的中文文档.

相关文章
|
1月前
|
JSON 自然语言处理 搜索推荐
BoostCompass( 查找功能实现 )
BoostCompass( 查找功能实现 )
31 7
|
1月前
|
前端开发 JavaScript
empty来显示暂无数据简直太好用,阻止用户复制文本user-select
empty来显示暂无数据简直太好用,阻止用户复制文本user-select
|
监控 Java Apache
Info 内容创建|学习笔记
快速学习 Info 内容创建
83 0
Info 内容创建|学习笔记
|
前端开发
前端工作总结208-page值不能修改
前端工作总结208-page值不能修改
57 0
前端工作总结208-page值不能修改
|
测试技术
软件测试面试题:page object设置模式中,是否需要在page里定位的方法中加上断言?
软件测试面试题:page object设置模式中,是否需要在page里定位的方法中加上断言?
107 0
重构——29以数据类取代记录(Replace Record with Data Class)
以数据类取代记录(Replace Record with Data Class):你需要面对传统编程环境中的记录结构;为该记录创建一个“哑”数据对象
1532 0
打印某个user在指定时间段内做过的personalization detail
This question is asked by consultant during Jerry’s supporting as dev angel. Partner wants to develop some report in the backend to track which users have performed what kinds of Fiori group personlization but he didn’t know the corresponding database table which contains the needed information, or
打印某个user在指定时间段内做过的personalization detail