fmt 命令详解与参数实测(Ubuntu 22.04)
GNU fmt 参数实测:默认 75 列段落重排、-w/-s/-u/-p/-c/-g 各参数与 fold 定位差异,Ubuntu 22.04(coreutils 8.32)全部命令回显实测。
fmt 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 GNU fmt 的每一个参数——默认 75 列段落重排、
-w目标宽度、-s只切长行不填充、-u词间统一空格、-p只处理带前缀的引用行、-ccrown margin 缩进结构、-g目标宽度,以及 fmt 与 fold 的定位差异,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- fmt 版本:GNU coreutils 8.32(
fmt --version实测) - fmt 属于 coreutils 基础工具集,Ubuntu 22.04 默认预装,无需额外安装
- 演示目录:
/root/demo/fmt/ - 测试数据:
para.txt(两行超长英文段落)、spaces.txt(词距不规则的行)、quote.txt(>开头的邮件引用行 + 普通行)、crown.txt(>前缀且第二行带缩进的两行回复)
二、命令概览
2.1 语法与测试数据准备
fmt 的语法是 fmt [-WIDTH] [OPTION]... [FILE]...:以空行为段落边界,把每个段落重排成目标宽度——长行切短、短行合并,输出到标准输出。-WIDTH 是 --width=DIGITS 的简写。与 fold 的机械定宽不同,fmt 理解"词"和"段落":断点选在词边界,重排后不存在被切开的单词。
先准备一套演示数据,后续所有参数实测都基于这套数据:
mkdir -p /root/demo/fmt
cat > /root/demo/fmt/para.txt <<'EOF'
The quick brown fox jumps over the lazy dog and keeps running across the open field until sunset. This paragraph has irregular line breaks and multiple spaces between words.
fmt is a simple text formatter that reflows each paragraph, filling and joining lines to reach the target width while blank lines act as paragraph separators.
EOF
cat > /root/demo/fmt/spaces.txt <<'EOF'
This line has double spaces between words everywhere.
Another line with irregular spacing inside.
EOF
cat > /root/demo/fmt/quote.txt <<'EOF'
> this is a quoted reply line that is quite long and needs to be reflowed to fit the width limit of the terminal window
> second quoted line continues the reply and adds more words so that it also wraps around when reformatted
plain text line is not touched by the prefix option
EOF
cat > /root/demo/fmt/crown.txt <<'EOF'
> first line of the reply carries the crown margin and long text that must wrap onto the following lines of the paragraph
> second line is indented and its prefix is reused for all wrapped lines produced below it
EOF
进入演示目录并确认数据就绪:
$ cd /root/demo/fmt
$ ls -l
total 16
-rw-r--r-- 1 root root 215 Oct 15 07:35 crown.txt
-rw-r--r-- 1 root root 335 Oct 15 07:35 para.txt
-rw-r--r-- 1 root root 279 Oct 15 07:35 quote.txt
-rw-r--r-- 1 root root 115 Oct 15 07:35 spaces.txt
$ cat para.txt
The quick brown fox jumps over the lazy dog and keeps running across the open field until sunset. This paragraph has irregular line breaks and multiple spaces between words.
fmt is a simple text formatter that reflows each paragraph, filling and joining lines to reach the target width while blank lines act as paragraph separators.
para.txt 两行分别长 175 与 158 字符且中间没有空行,因此是一个段落;quote.txt 前两行以 > 开头模拟邮件引用;crown.txt 第二行比首行多了缩进空格。
2.2 --help 全量回显
fmt --help 输出全部参数清单(实测原样保留,可作为参数速查):
Usage: fmt [-WIDTH] [OPTION]... [FILE]...
Reformat each paragraph in the FILE(s), writing to standard output.
The option -WIDTH is an abbreviated form of --width=DIGITS.
With no FILE, or when FILE is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-c, --crown-margin preserve indentation of first two lines
-p, --prefix=STRING reformat only lines beginning with STRING,
reattaching the prefix to reformatted lines
-s, --split-only split long lines, but do not refill
-t, --tagged-paragraph indentation of first line different from second
-u, --uniform-spacing one space between words, two after sentences
-w, --width=WIDTH maximum line width (default of 75 columns)
-g, --goal=WIDTH goal width (default of 93% of width)
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/fmt>
or available locally via: info '(coreutils) fmt invocation'
💡 说明:帮助明示两个关键默认值——
-w默认 75 列(不是 80),-g目标宽度默认为宽度的 93%(75 × 93% ≈ 70)。-t(tagged-paragraph)用于"首行缩进与次行不同"的标签式段落,本文演示数据不覆盖该参数,含义以帮助原文为准。
2.3 版本确认
$ fmt --version | head -1
fmt (GNU coreutils) 8.32
三、参数逐项实测
3.1 默认用法:段落重排(默认 75 列)
不带参数,fmt 以 75 列为上限、约 70 列为目标重排段落——两行输入被合并、重切成 5 行:
$ awk '{ print length($0) }' para.txt
175
158
$ fmt para.txt
The quick brown fox jumps over the lazy dog and keeps running across
the open field until sunset. This paragraph has irregular line breaks
and multiple spaces between words. fmt is a simple text formatter
that reflows each paragraph, filling and joining lines to reach the
target width while blank lines act as paragraph separators.
$ fmt para.txt | awk '{ print length($0) }'
68
69
68
67
59
$ fmt para.txt | wc -l
5
三个细节值得注意:
- 行长全部落在 59~69 之间,即"尽量接近 70(目标宽度)、绝不超过 75(上限)";
- 两个输入行之间没有空行,因此被视为同一个段落合并重排;
- 合并点
words.之后补成了两个空格(句间规范),但段内原有的and multiple三个空格原样保留——默认不压缩词距,见 3.4。
3.2 -w:指定目标宽度上限
-w WIDTH 同时改变上限与目标(目标仍取 93%)。40 列时输出 9 行:
$ fmt -w 40 para.txt
The quick brown fox jumps over the lazy
dog and keeps running across the open
field until sunset. This paragraph has
irregular line breaks and multiple
spaces between words. fmt is a simple
text formatter that reflows each
paragraph, filling and joining lines
to reach the target width while blank
lines act as paragraph separators.
$ fmt -w 40 para.txt | awk '{ print length($0) }'
39
37
38
36
38
32
36
37
34
行长在 32~39 之间,没有任何一行达到 40——fmt 总在词边界断行并留有余量,这与 fold 恰好 40 列硬切的风格完全不同。宽度压到 30 列时行数进一步增多:
$ fmt -w 30 para.txt
The quick brown fox jumps
over the lazy dog and keeps
running across the open
field until sunset. This
paragraph has irregular line
breaks and multiple spaces
between words. fmt is a
simple text formatter that
reflows each paragraph,
filling and joining lines to
reach the target width while
blank lines act as paragraph
separators.
💡 提示:
fmt -40与fmt -w 40等价(帮助原文:The option -WIDTH is an abbreviated form of --width=DIGITS),老脚本常见前者。
3.3 -s:只切长行,不填充短行
-s(--split-only)只做"收缩":超过宽度的长行被切开,但已经短于宽度的行不会被合并填充:
$ fmt -s para.txt
The quick brown fox jumps over the lazy dog and keeps running across
the open field until sunset. This paragraph has irregular line breaks
and multiple spaces between words.
fmt is a simple text formatter that reflows each paragraph, filling
and joining lines to reach the target width while blank lines act as
paragraph separators.
$ fmt -s para.txt | awk '{ print length($0) }'
68
69
36
67
68
21
与 3.1 的默认重排对比:默认把两行合并成 5 行,而 -s 产出 6 行——第一输入行切成 68/69/36 三行、第二输入行切成 67/68/21 三行,两段之间没有跨行合并,36 与 21 的短行原样保留。对本来就很短的行,-s 完全不动:
$ printf 'a b c\nd e f\ng h i\n' > shrink.txt
$ fmt -s shrink.txt
a b c
d e f
g h i
$ rm -f shrink.txt
💡 提示:想"只把超长行变短、其余保持原状"(比如处理日志或注释里的宽行)用
-s;想得到整齐的段落用默认重排。
3.4 -u:词间统一单空格
-u(--uniform-spacing)把词间空格统一成"词间 1 个、句末 2 个"。先看输入的双空格/三空格:
$ cat spaces.txt
This line has double spaces between words everywhere.
Another line with irregular spacing inside.
$ fmt -u spaces.txt
This line has double spaces between words everywhere. Another line with
irregular spacing inside.
$ fmt -u spaces.txt | cat -A
This line has double spaces between words everywhere. Another line with$
irregular spacing inside.$
cat -A 确认:everywhere. 句号后恰好两个空格,其余词间均为单空格,两行输入被合并重排。作为对照,不加 -u 的默认重排会保留原有词距:
$ fmt spaces.txt
This line has double spaces between words everywhere. Another
line with irregular spacing inside.
默认输出里双空格、三空格原样保留(只在合并点补句末双空格)。需要"净化词距"必须显式加 -u。
💡 提示:
-u可以和-w组合使用,例如"统一词距 + 40 列重排",见 4.2 实战。
3.5 -p:只重排带前缀的行(邮件引用)
-p STRING 只处理以 STRING 开头的行,重排后把前缀重新贴回每一行——典型场景是邮件回复的 > 引用:
$ cat quote.txt
> this is a quoted reply line that is quite long and needs to be reflowed to fit the width limit of the terminal window
> second quoted line continues the reply and adds more words so that it also wraps around when reformatted
plain text line is not touched by the prefix option
$ fmt -p ">" quote.txt
> this is a quoted reply line that is quite long and needs to be reflowed
> to fit the width limit of the terminal window second quoted line
> continues the reply and adds more words so that it also wraps around
> when reformatted
plain text line is not touched by the prefix option
两条引用行被重排成 4 行,每行都重新带上 > 前缀;无前缀的第三行原样输出、完全不受影响。配合 -w 控制引用行宽度:
$ fmt -p ">" -w 40 quote.txt
> this is a quoted reply line that is
> quite long and needs to be reflowed
> to fit the width limit of the
> terminal window second quoted line
> continues the reply and adds more
> words so that it also wraps around
> when reformatted
plain text line is not touched by the prefix option
💡 提示:
-p匹配的是"行首的 STRING",重排时 fmt 自动把前缀回贴到每一行,保证输出仍是合法的引用格式。
3.6 -c:crown margin(保留首两行缩进结构)
-c(--crown-margin)让段落"戴冠":首行保持自己的缩进/前缀结构,后续所有折行采用第二行的缩进。先看一个重要实测结论——对纯 > 字符前缀(无空白缩进差异)的段落,-c 与不加 -c 输出完全相同:
$ cat crown.txt
> first line of the reply carries the crown margin and long text that must wrap onto the following lines of the paragraph
> second line is indented and its prefix is reused for all wrapped lines produced below it
$ fmt -c -w 40 crown.txt
> first line of the reply carries
the crown margin and long text that
must wrap onto the following lines
of the paragraph > second line is
indented and its prefix is reused for
all wrapped lines produced below it
$ fmt -w 40 crown.txt
> first line of the reply carries
the crown margin and long text that
must wrap onto the following lines
of the paragraph > second line is
indented and its prefix is reused for
all wrapped lines produced below it
两次输出逐字相同:第二行的 > 没有被识别为前缀结构,而是被当成正文里的一个"单词"留在行中。-c 关注的是空白缩进结构,字符前缀应该交给 -p(见 3.5)。用真实缩进的段落验证 -c 的本职行为——首行缩进 4 空格、第二行缩进 6 空格:
$ cat indent.txt
first line indented four spaces with long text that must wrap onto more lines to see the margin behavior clearly
second line indented six spaces, its indentation becomes the body indent used for wrapped lines below
$ fmt -c -w 40 indent.txt
first line indented four spaces
with long text that must wrap
onto more lines to see the
margin behavior clearly second
line indented six spaces,
its indentation becomes the
body indent used for wrapped
lines below
$ fmt -w 40 indent.txt
first line indented four spaces
with long text that must wrap
onto more lines to see the margin
behavior clearly
second line indented six spaces,
its indentation becomes the
body indent used for wrapped
lines below
$ rm -f indent.txt
对比清晰:加 -c 后两行合并为一个段落,首行保持 4 空格缩进,所有续行统一使用第二行的 6 空格缩进("冠"与"身"分离);不加 -c 时两行是两个独立段落、各自保持缩进。这就是 crown margin 的语义——首行样式独立、正文样式取自第二行。
💡 提示:
-t(tagged-paragraph)是-c的近亲,适用于"首行缩进与次行不同、且首行独立成段"的标签式段落;本组演示数据未覆盖,用法以帮助原文与 info 手册为准。
3.7 -g:目标宽度(比上限更早换行)
-g WIDTH 单独指定目标宽度(可远小于上限 -w),fmt 尽量在目标宽度处断行,只有收尾余文等情况才允许超到上限:
$ fmt -w 75 -g 30 para.txt
The quick brown fox jumps
over the lazy dog and keeps
running across the open field
until sunset. This paragraph
has irregular line breaks and
multiple spaces between words.
fmt is a simple text formatter
that reflows each paragraph,
filling and joining lines to
reach the target width while blank lines act as paragraph separators.
$ fmt -w 75 -g 30 para.txt | awk '{ print length($0) }'
25
27
29
28
29
30
30
28
28
69
前 9 行都控制在 25~30 之间(目标 30);最后一行 69 列——它是段落的收尾余文,fmt 不再强行切短,只要不超过上限 75 即可。这正是 goal 与 max 的语义差异:-g 是"尽量",-w 是"绝不"。
💡 提示:默认
-g取-w的 93%(帮助原文)。想让行更"参差自然"可把-g调小,想让行更满可调大。
3.8 fmt 与 fold 的定位差异
同样给 40 列宽度,fold 是机械硬切、fmt 是智能重排,并排对比:
$ fold -w 40 para.txt | head -5
The quick brown fox jumps over the lazy
dog and keeps running across the open fi
eld until sunset. This paragraph has irr
egular line breaks and multiple spaces
between words.
$ fmt -w 40 para.txt | head -5
The quick brown fox jumps over the lazy
dog and keeps running across the open
field until sunset. This paragraph has
irregular line breaks and multiple
spaces between words. fmt is a simple
fold 把 fi|eld、irr|egular 从单词中间切开且每行恰好 40 列;fmt 每行都在词边界断开、行长有余量。一句话定位:fold 管"宽度"不管"语义",fmt 管"语义"顺带控制宽度。
💡 技术拓展:文本重排工具不止这两个,常见选择对比——
工具 策略 典型场景 fold 按宽度硬切(可 -s空格断)管道定宽、硬性宽度输出 fmt 段落级填充与合并(本文主角) 邮件、README、提交说明排版 par 更强的段落格式化(悬挂缩进、对齐) 复杂排版需求(需另行安装) 编辑器软换行 仅显示时换行,不改文件 阅读场景 本文实测环境预装了 fold 与 fmt,两者组合已覆盖"机械定宽 + 智能重排"两类需求。
四、实战示例
4.1 管道里快速重排长句
对动态生成的长句(命令输出、提示文案)直接在管道里定宽重排:
$ printf 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen\n' | fmt -w 30
one two three four five six
seven eight nine ten eleven
twelve thirteen fourteen
fifteen sixteen
一行 96 字符的长句被重排成 4 行 30 列以内的文本,单词零损伤。
4.2 统一词距并定宽重排
先净化不规则词距再排版,一条命令完成:
$ fmt -u -w 40 spaces.txt
This line has double spaces between
words everywhere. Another line with
irregular spacing inside.
双空格/三空格全部归一(句末保留两空格),段落按 40 列重排。适合清洗从网页、PDF 复制出来的文本。
4.3 只切长行的保守整理
处理不能合并行的文本(如带固定行结构的说明文件)时,用 -s 只把超宽行切短,并配合 head 预览:
$ fmt -w 60 -s para.txt | head -3
The quick brown fox jumps over the lazy dog and keeps
running across the open field until sunset. This paragraph
has irregular line breaks and multiple spaces between
超长的两行被切到 60 列以内,原有短行不被合并,词距 and multiple 也未被压缩——-s 的"只收缩"语义在管道预览里很安全。
五、注意事项与常见问题
Q1:fmt 默认宽度是 80 列吗?
不是。帮助原文明示 maximum line width (default of 75 columns),目标宽度默认为 75 的 93%(约 70 列),3.1 实测行长 59~69 与此吻合。写脚本按 75 规划,不要想当然用 80。
Q2:为什么词间的多个空格没有被压缩?
默认重排保留既有词距(3.4 对照实测),只有 -u 才把词间统一成单空格、句末两空格。这与很多编辑器的"reflow"行为不同,容易踩坑。
Q3:-s 处理后短行为什么没有被合并?
-s(--split-only)的语义就是"切长行、不填充"(见 3.3 实测):短于宽度的行保持原样,段落之间也不做跨行合并。要合并短行请用默认重排。
Q4:邮件引用行被混进正文一起重排了?
默认 fmt 不区分引用;加 -p ">" 后只重排以 > 开头的行,其余行原样输出(见 3.5 实测)。
Q5:-c 加了没效果?
-c 识别的是空白缩进结构,不是 > 这类字符前缀。实测中纯 > 前缀段落加不加 -c 输出相同(见 3.6),字符前缀场景用 -p;-c 的正确用法是首行与次行缩进不同的段落。
Q6:fmt 会把两个自然段合并吗? 不会。空行是段落边界(帮助与手册均以此为准),只有同段内的行才会互相合并;3.1 中两行被合并是因为它们之间没有空行。想保持分段,确保段与段之间有空行。
Q7:可以对代码或配置文件用 fmt 吗?
不要。fmt 会重排行结构并按自身规则调整空格,代码、YAML、表格类文本会被破坏;确有超宽注释行需求时用 -s 且先备份,或干脆用编辑器软换行。
Q8:fmt 与 fold 怎么选? 机械定宽(管道、打印、硬性宽度)选 fold;段落语义重排(邮件、文档)选 fmt。两者并排对比实测见 3.8。
六、参考链接
- GNU coreutils 官方手册(fmt 章节):https://www.gnu.org/software/coreutils/manual/html_node/fmt-invocation.html
- 在线文档:https://www.gnu.org/software/coreutils/fmt
- 本机帮助:
fmt --help、man fmt(Ubuntu 22.04 内置)