《Shell 大道:筑基篇(下)—— 流控筑根基,数据任驱驰》
文章目录
- 前言
- 一、逻辑运算符
- 1.1 `&&`(逻辑与)
- 1.2 `||`(逻辑或)
- 1.3 组合使用:`A && B || C`
- 二、echo 命令与输出流
- 2.1 输出到标准输出(`stdout`)
- 2.2 输出到标准错误(`stderr`)
- 三、标准文件描述符(`FD`)
- 四、重定向操作
- 4.1 `>` 与 `>>`:重定向输出`stdout`
- 4.2 `2>` 与 `2>>`:重定向错误输入 `stderr`
- 4.3 `<`:重定向输入
- 4.4 `<(...)`:进程替换
- 4.3 同时重定向 `stdout` 与 `stderr`
- 4.3.1 POSIX 推荐写法
- 4.3.2 Bash 简写
- 五、丢弃输出:`/dev/null`
- 六、管道` | `与错误流处理
- 6.1 基本用法
- 6.2 同时传输 `stdout `和 `stderr`
- 七、进阶技巧:自定义文件描述符
- 7.1 从“一切皆文件”的特点理解重定向
- 总结
前言
【筑基进阶,流控入微】
道友已修成筑基初阶秘术,能以流程控制驭符阵、以函数化繁为简,然符阵运转的核心 ——“灵气(数据)流转”,仍需进一步深造。练气期,汝仅能借read
收灵气、凭echo
散真气,对数据走向毫无掌控;而筑基进阶,需以 “逻辑运算符” 为开关,以 “重定向” 为改道符,以 “管道与文件描述符” 为传功索,让灵气按需流转、不溢不散。
本篇将授汝 “流控三术”:其一为&&
与||
的 “开关妙法”,依符阵(命令)成败定后续行止;其二为重定向(>
/>>
/2>
)的 “改道秘术”,将灵气归入正途(stdout
)、岔路(stderr
)或黑洞(/dev/null
);其三为管道(|
)与文件描述符(0/1/2)的 “传功要诀”,串联多符阵、多通道协同运转。此三术乃筑基进阶关键,练至大成,可让符阵灵气调度无滞,为后续应对 “异常劫雷(错误处理)” 筑牢根基。
一、逻辑运算符
1.1 &&
(逻辑与)
含义:仅当左侧命令成功(退出状态码为 0)时才执行右侧命令。
因此可以使用&&
当作一个特殊的if
循环,&&
左侧为if的判断条件,右侧为判断成功执行的命令。
示例:
false && echo "成功"
# 无输出,因为 false 失败true && echo "成功"
成功
# true 成功,执行 echo
1.2 ||
(逻辑或)
含义:仅当左侧命令失败(退出状态码非 0)时才执行右侧命令。
同&&
,||
也可以当做一个特殊的if
循环,&&
左侧为if的判断条件,右侧为判断失败后执行的命令。
示例:
false || echo "左侧失败,执行此处"
# 左侧失败,执行此处true || echo "不会执行"
# 无输出,因为 true 成功
1.3 组合使用:A && B || C
注意:从左到右结合,等价于 (A && B) || C
。
示例:
$ false && echo yes || echo fallback
fallback
# (false && echo yes) 失败,执行 fallback
二、echo 命令与输出流
2.1 输出到标准输出(stdout
)
用于程序输出正常的、预期的结果。
示例:
echo "hello world"
hello world
2.2 输出到标准错误(stderr
)
专门用于输出错误信息或异常提示。
示例:
echo "this is error" >&2
# 文本发送到 stderr
三、标准文件描述符(FD
)
在 Unix、Linux 及类 Unix 操作系统中,标准文件描述符(Standard File Descriptors) 是内核为每个进程预分配的、用于与外部设备 / 数据流交互的 “默认通道”。它们本质是整数标识,对应进程打开的文件(广义的 “文件”,包括终端、管道、网络套接字等),让程序无需手动指定交互对象就能完成基础输入、输出和错误处理。
0
:stdin(标准输入)1
:stdout(标准输出)2
:stderr(标准错误)
示例:
echo "out" # 输出到 stdout
echo "err" >&2 # 输出到 stderr
四、重定向操作
4.1 >
与 >>
:重定向输出stdout
改变命令的输出目的地,从默认的终端屏幕改为写入文件。
>
:覆盖写入文件>>
:追加写入文件
示例(覆盖):
echo "first" > file.txt
echo "second" > file.txt
cat file.txt
示例(追加):
echo "first" > file.txt
echo "second" >> file.txt
cat file.txt
4.2 2>
与 2>>
:重定向错误输入 stderr
将命令执行时产生的错误信息(如 “文件不存在”)重定向到指定位置,而非默认显示在终端。
2>
:将错误信息覆盖写入文件2>>
:将错误信息追加写入文件
示例:
ls /no/such/path 2>err.txt
cat err.txt
4.3 <
:重定向输入
改变命令的输入来源,从默认的键盘输入改为从文件读取。
示例:
#! /bin/bash
# user_info.sh:读取姓名和年龄并输出read -p "请输入你的姓名:" name # 读取输入赋值给 name 变量
read -p "请输入你的年龄:" age # 读取输入赋值给 age 变量# 输出结果
echo -e "\n你的信息:"
echo "姓名:$name"
echo "年龄:$age"
sh demo16.sh < test.sh #在不直接输入参数的情况下用test.sh中的内容进行输入
4.4 <(...)
:进程替换
在 Shell 中,<(…) 被称为进程替换(Process Substitution),它可以将一个命令的输出作为一个临时文件(或文件描述符)传递给另一个命令。
# 将grep的输出作为wc -l的输入
wc -l < <(grep "error" file.txt)
grep "ERROR" <(cat /var/log/syslog)
#等价于 cat /var/log/syslog | grep "ERROR",但用进程替换的写法更直观。
4.3 同时重定向 stdout
与 stderr
4.3.1 POSIX 推荐写法
command >out.txt 2>&1
示例:
bash -c 'echo out; echo err >&2' >both.txt 2>&1
cat both.txt
注意顺序:以下写法错误,stderr 仍会输出到终端:
bash -c 'echo out; echo err >&2' 2>&1 >both.txt
4.3.2 Bash 简写
在Bash中可以使用简写。
command &>file # 同时重定向 stdout 和 stderr
command |& other # 同时管道传输 stdout 和 stderr
示例:
bash -c 'echo out; echo err >&2' &> both.txt
cat both.txt
五、丢弃输出:/dev/null
含义:将不需要的输出重定向到 /dev/null
(黑洞设备)。
示例:
- 丢弃 stdout:
some_command > /dev/null
- 丢弃 stderr:
some_command 2> /dev/null
- 同时丢弃 stdout 和 stderr:
some_command > /dev/null 2>&1 # 或some_command &> /dev/null
六、管道|
与错误流处理
6.1 基本用法
含义:将前一个命令的 stdout 作为下一个命令的 stdin。
管道|
,重定向输入>
,重定向输出<
的三者间的区别
- 管道
|
:从一个命令到另一个命令 - 重定向输入
>
:从一个命令到一个文件 - 重定向输出
<
:从一个文件到一个命令
示例:
echo -e "apple\nbanana" | grep banana
6.2 同时传输 stdout
和 stderr
command 2>&1 | grep something
# 或(Bash)
command &> | grep something
command |& grep something
示例:
bash -c 'echo out; echo err >&2' 2>&1 | sed -n 'p'
七、进阶技巧:自定义文件描述符
用途:在脚本中管理多个输出流。
示例:
exec 3>mylog.txt # 打开 FD 3 指向文件
echo "hello" >&3 # 写入 FD 3
exec 3>&- # 关闭 FD 3
cat mylog.txt
7.1 从“一切皆文件”的特点理解重定向
从上面的打开“FD3”输出流,以及“exec 3>mylog.txt”、“echo “hello” >&3”的写法不难得出“&1”、“&2”也是一个指向文件的输出流。而作为一个“一切皆文件”的系统,“&1”、“&2”指向的是命令行页面,因为当不使用重定向时,正确或错误的信息会直接输出在命令行的界面上,也就是说“命令行界面也被视为了一个文件”,这也就能理解为什么>
、<
这些符号不直接叫输入、输出,而是叫重定向输入、重定向输出。
bash -c 'echo out; echo err >&2' >both.txt 2>&1
bash -c 'echo out; echo err >&2' 2>&1 >both.txt
再用上方的例子理解一下重定向:
bash -c 'echo out; echo err >&2'
: 执行一个子bash,在其中执行了“echo out; echo err >&2”命令echo out
:实际是echo out >&1
,将>&1
进行了省略,作用是输出“out”给FD1echo err >&2
:这边的作用是输出“err”给FD2
>both.txt
:这一部分的命令同样进行了省略,实际为1>both.txt
,意思是将FD1输出流的地址从命令行界面重定向为了一个文件both.txt2>&1
:这的作用则是将FD2输出流的地址重定向到FD1输出流的地址,也因为这样>both.txt
、2>&1
的前后顺序,会对最后的结果产生影响,2>&1
在前时先进行了FD2输出流的地址重定向到FD1输出流的地址的过程,此时FD2的指向文件仍是命令行界面,再执行>both.txt
则是仅再次改变了FD1输出流的输出地址,最终结果就变成了再命令行界面输出“err”,而在both.txt
输出了“out”。同理,可以看出2>&1
在后时的结果是'echo out; echo err >&2'
的命令都输出到了“both.txt”中
总结
【流控功成,筑基圆满】
贺喜道友!筑基进阶 “流控” 神通已成,至此筑基之境圆满!
此刻,汝已通晓逻辑运算符的 “开关之道”:&&
仅在前方符阵成功时续接术法,||仅在前方符阵失败时补位,二者结合可精准控制符阵流程;熟稔重定向的 “改道之术”:>
/>>
掌控标准输出,2>
/2>>
收纳错误信息,更能以&>
同时调度双流向,让数据按需归位;亦掌握管道与文件描述符的 “协同之法”:管道串联多符阵,让灵气层层传递;自定义文件描述符(如 FD3)可拓展数据通道,应对复杂场景。
此流控之术虽不似流程控制那般显化 “符阵框架”,却是筑基期的 “内功核心”—— 若无流控,符阵灵气易乱、数据易失,后续构建复杂脚本、处理异常皆无从谈起。今汝筑基道基无瑕,既能搭符阵之架,又能控灵气之流,已具备向《金丹篇》迈进的资格。下一站,吾在金丹之境,静候道友前来!