竖线 |:管道、按位或、掩码组合

一、前言

在 Linux 学习过程中,绝大多数人都会被同一个符号 | 搞混淆:

命令行里它是管道、代码里它是位运算、系统函数参数里它是标志叠加。

很多人疑惑:明明都是竖线,为什么功能完全不同?

标准答案:符号本身没有任何意义,解析环境决定意义。

Shell 解释器、C语言编译器、Linux 内核,三套完全不同的解析规则,互不干涉。


二、Shell 终端中:| 是「管道符」

1. 作用

Shell 里的|和数学运算没有任何关系。

它的唯一作用:把前一个命令的输出,交给后一个命令当输入,实现进程数据接力。

2. 特点

  • 多个命令同时运行(流水线并发)

  • 数据在内存流动,不产生临时文件

  • 下游依赖上游输出,实现链式数据处理

3. 示例

bash 复制代码
ls -l | grep txt | wc -l
cat app.log | grep error | awk '{print $5}' | sort | uniq -c

4. Shell 极易混淆四组符号

  • | 管道:数据接力

  • || 逻辑或:前命令失败,才执行后命令

  • && 逻辑与:前命令成功,才执行后命令

  • & 后台并行:两个命令独立同时跑


三、编程语言中:| 是「按位或运算符」

在 C / C++ / Python / Java 中,| 是标准 二进制位运算,纯粹数学计算,和管道无关。

1. 运算规则

有1则1,全0才0,逐位独立计算。

cs 复制代码
0b0010 | 0b0100 = 0b0110

2. 基础示例

cs 复制代码
int a = 2;    // 0010
int b = 4;    // 0100
int res = a | b; // 0110 = 6

四、系统编程中:| 是「掩码叠加」(最容易混淆)

你写 open、socket、epoll 时看到的:

O_WRONLY | O_CREAT | O_TRUNC

这里绝对不是管道,是标准按位或运算。

1. 内核 flag 本质

Linux 所有 flag 本质都是 整数掩码:

每一个二进制 bit 代表一个开关功能。

内核宏定义简化如下:

cs 复制代码
#define O_WRONLY  0001  // 只写
#define O_CREAT   0100  // 不存在则创建
#define O_TRUNC   1000  // 存在则清空

2. 按位或叠加多个功能

使用 | 可以同时开启多个开关:

cs 复制代码
  0001  O_WRONLY
| 0100  O_CREAT
| 1000  O_TRUNC
= 1101

最终结果同时拥有:只写、创建、清空三种能力。

3. 为什么不能用加号 +

加法会进位、会丢 bit,会导致功能错乱;

按位或只置1、不进位,是唯一安全的叠加方式。

cs 复制代码
#define A 0b0010
#define B 0b0010

A + B = 0b0100  // 错误,进位丢失
A | B = 0b0010  // 正确,保留开关状态

4. 经典系统调用统一写法

cs 复制代码
// 文件打开
open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);

// 非阻塞 socket
socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

// epoll 多事件监听
ev.events = EPOLLIN | EPOLLOUT;

五、一张表彻底终结混淆

使用场景 符号含义 本质 示例
Shell 命令行 管道符 进程数据流传递 `ls
代码数值运算 按位或 二进制数学运算 `x = a
系统函数 flag 掩码按位或 叠加多个功能开关 `O_WRONLY

六、最终总结

  • 终端里的 | 是管道,负责命令数据流接力;

  • 代码里的 | 是按位或,负责二进制运算;

  • open/socket 参数里的 | 是掩码叠加,用来组合多个系统功能;

  • 永远不要用 + 代替 | 组合系统标志;

  • 符号不决定功能,环境决定一切。

相关推荐
WeiXin_DZbishe12 分钟前
基于springboot装修风格选择系统的设计与开发-计算机毕设【课程设计】77964
java·vue.js·spring boot·后端·python·php·课程设计
XZ-07000118 分钟前
week9-三元表达式
java·前端·python
云和数据.ChenGuang27 分钟前
name=“张三“ age=18 weight=100.3 print (name,age,weight)
java·服务器·前端
benchmark_cc32 分钟前
量化项目启动时,应该先设计数据接口还是先编写策略?从系统架构角度做出正确选择
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
2601_9628857233 分钟前
如何用 Python 判断一只股票“追涨”还是“抄底”更有效?
android·开发语言·python
Yeswater1 小时前
从 NIO 到 Netty:五个坑,和一张把它填平的基础设施网
java·后端·netty
denlaku1 小时前
JDK 15 新特性详解
java·开发语言
荣码1 小时前
LangSmith可观测性:AI应用出bug根本不知道哪里出了问题,我踩了4个坑
java·python
滴滴答答哒1 小时前
C# 技巧:优雅实现对象的“局部更新”与“字段合并”
开发语言·c#
灯澜忆梦1 小时前
【面向对象编程c++】| 指针与自定义数据类型
开发语言·c++·算法