那个叫「竖线」的符号:一条线,既连接一切,又分隔一切
目录
- 贝尔实验室那条最省的线
- 连接:把 A 的出口,接进 B 的入口
- 分隔:被夹起来的,是「内部」
- 表格:竖线画出来的格子
- 边界,既是连接也是分隔
- 我把 8160 个竖线,按工种分了一次类
同一个字符,有两种画法。
A | B——竖线站在两个东西中间。ps aux | grep node,一行命令,两个进程被它接在一起,前一个的输出直接灌进后一个的输入。
|A|——竖线把东西夹在中间。|-3| 的意思是 3:不是「负三」,是「负三离零有多远」。
第一种画法里,它是连接符。第二种画法里,它是分隔符。同一个字符,一个键按出来的同一根线。
而这,恰好是边界的定义。
贝尔实验室那条最省的线
竖线不是被设计出来的。它是捡来的。
打字机时代,键盘上有一批「没被分配正经工作」的字符:#、@、&、%、~、|。它们的 ASCII 码位是 0x23、0x40、0x26、0x25、0x7E、0x7C——排在字母数字后面,像是字母表收工后剩下的边角料。
1960 年代,贝尔实验室的 Doug McIlroy 在一份备忘录里写了一个想法:程序应该像水管一样,一个的输出接进下一个的输入,而连接它们的,就是这条竖线。后来 Ken Thompson 在 Unix 里把它变成了现实。
这个想法后来被称为 Unix 哲学:每个程序只做一件事,做好它;程序之间的协作,靠管道完成。
也就是说——这个符号的出现,比它连接的 Unix 还早。它是整个 Unix 世界观的语法标记。
有意思的是,McIlroy 当年发明的是「管道」这个概念,不是竖线本身。竖线在键盘上躺了几十年,直到有人发现「两个程序之间那个口子」,恰好可以用这条没人要的线来画。
连接:把 A 的出口,接进 B 的入口
管道的机制今天还在被几十亿人每天触发,只是没人会停下来看它一眼。
echo 'hello' | wc -c
# 6
echo 把 hello 打出来,wc -c 数了数——6 个字节(hello\n)。中间那条竖线,把前一个进程的 stdout 接进了后一个进程的 stdin。
ls /usr/bin | grep -c '^py'
# 16
这台机器上,/usr/bin 里以 py 开头的程序有 16 个。ls 列出来,grep 过滤,-c 计数——三个进程,两条竖线。
ps aux | grep -i node | grep -v grep | wc -l
# 1
四段管道。ps 列出所有进程,grep 筛出 node,grep -v 去掉 grep 自己,wc -l 数行。每一条竖线,都是一次进程间的握手。
在管道之前,程序之间交换数据要靠临时文件:A 写一个文件,B 读那个文件,然后有人负责删掉它。管道把这套「先落盘再读取」的仪式压缩成了一个字符。
一个字符,取代了一整个文件系统操作。这是符号史上性价比最高的一次征用。
分隔:被夹起来的,是「内部」
竖线的另一面,是分隔。
数学里,|-3| 读作「负三的绝对值」。它问的不是「负三是几」,而是「负三离零有多远」——答案是 3。两条竖线把数字夹在中间,像是在说:里面的东西,请单独看。
同样的逻辑,在 20 世纪初被 Sheffer 借去表示逻辑学里的 NAND——「not both」,不是两者都成立。两条线把两个命题夹在一起,表示「它们不能同时为真」。
正则表达式里,cat|dog 的意思是「匹配 cat 或者 dog」——竖线在这里是分隔符,把两个候选选项隔开。Python 实测:
import re
re.findall(r'cat|dog', 'a cat and a dog')
# ['cat', 'dog']
位运算里,5 | 3 等于 7——二进制 101 | 011 = 111。竖线在这里是「或」,把两股二进制流合并成一股。这跟管道是同一件事的两种说法:管道是进程级的「或」,位或是数据级的「或」。
有意思的是,竖线做分隔符时,恰好也在做连接:绝对值把「内部」从「外部」隔开,但正因为它隔开了,内部才成其为内部。正则的 cat|dog 把两个选项分开,但正因为它分开,两个选项才能同时存在于一条规则里。
分隔,是另一种形式的连接。
表格:竖线画出来的格子
如果你读到这里,你正在看一个由竖线组成的表格——不对,你正在看一个由竖线组成的目录。
Markdown 表格是竖线最著名的「民用」岗位:
| 维度 | 在家 | 咖啡店 |
|------|------|--------|
| 专注度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 成本 | 0 | 一杯桂花拿铁 |
竖线在这里既不连接进程,也不夹数字——它画格子。每一列被竖线隔开,但正因如此,行与行才能对齐成一张表。没有竖线,这些内容只是一堆散落的词。
我扫了自己的博客数据库:全库 548 篇已发布文章里,166 篇正文含竖线,总共 2787 个——而且绝大多数是表格分隔符。也就是说,竖线在我自己的写作里,干的是一份「排版工人」的活。
边界,既是连接也是分隔
到这里,竖线的所有工种可以并成一排看:
| 工种 | 竖线在做什么 | 连接 or 分隔 |
|---|---|---|
| Unix 管道 | ps | grep 把两个进程接起来 |
连接 |
| 绝对值 | |-3| 把数字夹起来 |
分隔 |
| 正则 | cat|dog 把选项隔开 |
分隔 |
| 位或 | 5 | 3 把两股二进制合并 |
连接 |
| 表格 | 把列分开画成格子 | 分隔 |
它同时当着连接符和分隔符——而且这两件事是同一件事。
国界线把两个国家分开,但也正是这条线,定义了两边各自的存在。没有边界,就没有「这边」和「那边」。管道的竖线把 A 的输出接进 B 的输入,但同时也把 A 和 B 保持为两个独立的进程——**正因为它们被隔开,它们才能被连接。**绝对值把「内部」从「外部」隔开,内部才成其为内部。
这就是竖线和其他符号最不一样的地方。& 从「连接」演变成了「分隔」——那是时间线上的漂移。而竖线从一开始就同时是两者:它连接的每一对东西,正因为被它隔开,才各自成立。
顺便说一句中文。汉字里没有竖线语法——方块字不需要一根线来连接或分隔,笔画自己就是边界。所以中文用户第一次认识竖线,几乎都在表格和代码里:它是「竖线」(以形命名)、是「管道符」(以用命名)、是「杠」(随手叫的)。英文则干脆叫它 pipe——以用命名,命名里就带着它最著名的那份工。中文看它的形状,英文看它的用处。一个字符的两种命名哲学,本身就是一场连接与分隔。
我把 8160 个竖线,按工种分了一次类
代码即证据。我扫了本站的源码目录(420 个 .vue/.ts/.js/.py/.css 文件),数了数竖线的工龄:
- 单竖线
|出现 8160 次 - 双竖线
||(逻辑或)出现 1802 次 - 平均每个文件 19.4 个竖线
这 8160 个竖线里,有管道、有正则、有位或、有类型联合、有默认参数——我在自己的代码库里,替它按工种分了一次类。
再顺手验证一遍核心机制:
echo 'hello' | wc -c # 6 —— 管道连接
python3 -c "print(5 | 3)" # 7 —— 位或合流
python3 -c "print(abs(-3))" # 3 —— 绝对值分隔
python3 -c "import re; print(re.findall(r'cat|dog', 'a cat and a dog'))" # ['cat', 'dog'] —— 正则分隔
四条命令,四种语义,全部零歧义。竖线没有因为身兼数职而精神分裂——它只是把「边界」这件事做到了极致。
ASCII 0x7C,键盘上 Shift+\ 按出来的那根线。字母表收工后剩下的边角料,如今是 Unix 世界观的语法标记、数学的距离符号、正则的选项分隔符、表格的格子线。
符号换工作系列写到这儿,六位主角全数登场:# 被五十个行业征用,~ 从数学漂到撒娇,@ 从羊价变成身份,& 从连词变成分隔,% 同时打着四份工,| 一边连接一切,一边分隔一切。
它们都不是被设计出来的。它们只是恰好在那里,等着被需要。而需要它们的世界,从来没有问过它们原本叫什么。
一根线画下去,两边各有一个世界。它们能各自成立,恰恰是因为这根线。
评论(0)
暂无评论,来写第一条吧~