乐闻世界logo
搜索文章和话题

Shell 脚本中的重定向和管道机制是什么?如何使用?

3月6日 21:33

Shell 脚本中的重定向和管道机制是进程间通信和数据流控制的重要方式。

标准输入输出

三种标准流

bash
stdin (0) # 标准输入 - 默认从键盘读取 stdout (1) # 标准输出 - 默认输出到屏幕 stderr (2) # 标准错误 - 默认输出到屏幕

输出重定向

重定向标准输出

bash
# 覆盖重定向(>) echo "Hello" > file.txt # 创建或覆盖文件 ls -l > filelist.txt # 追加重定向(>>) echo "World" >> file.txt # 追加到文件末尾 date >> log.txt

重定向标准错误

bash
# 重定向错误输出 ls /nonexistent 2> error.log # 追加错误输出 ls /nonexistent 2>> error.log # 同时重定向输出和错误 command > output.txt 2>&1 command &> output.txt # Bash 4.0+ 简写 # 分别重定向 command > output.txt 2> error.txt

丢弃输出

bash
# 丢弃标准输出 command > /dev/null # 丢弃错误输出 command 2> /dev/null # 丢弃所有输出 command > /dev/null 2>&1 command &> /dev/null

输入重定向

从文件读取

bash
# 从文件读取输入 wc -l < file.txt # 多行输入 cat << EOF > script.sh #!/bin/bash echo "Hello, World!" EOF

Here Document

bash
# 多行输入 cat << EOF This is line 1 This is line 2 This is line 3 EOF # 使用变量 name="John" cat << EOF Hello, $name! EOF # 禁用变量替换 cat << 'EOF' This is $name - not expanded EOF

Here String

bash
# 单行输入 wc -w <<< "Hello World" # 处理变量 text="Hello World" grep "World" <<< "$text"

管道

基本管道

bash
# 将一个命令的输出作为另一个命令的输入 ps aux | grep nginx cat file.txt | grep "pattern" ls -l | sort -k5 -n # 多个管道连接 cat file.txt | grep "pattern" | wc -l

管道与重定向结合

bash
# 管道输出到文件 command | tee output.txt # 管道错误输出 command 2>&1 | grep "error" # 从管道读取输入 while read line; do echo "Line: $line" done < <(ls -l)

进程替换

基本语法

bash
# 输出进程替换(<()) diff <(ls dir1) <(ls dir2) # 输入进程替换(>()) tar -cf >(gzip > archive.tar.gz) directory/ # 多个进程替换 paste <(cut -f1 file1) <(cut -f2 file2)

实际应用

bash
# 比较两个目录 diff <(ls dir1) <(ls dir2) # 合并多个文件 paste <(cut -d: -f1 /etc/passwd) <(cut -d: -f3 /etc/passwd) # 实时监控 tail -f /var/log/syslog | grep --line-buffered "ERROR" | tee errors.log

高级重定向

文件描述符操作

bash
# 打开自定义文件描述符 exec 3> output.txt echo "Line 1" >&3 echo "Line 2" >&3 exec 3>&- # 从文件描述符读取 exec 4< input.txt read line <&4 echo "$line" exec 4<&- # 交换文件描述符 command 3>&1 1>&2 2>&3

同时读写

bash
# 同时读写同一文件 exec 3<> file.txt read -u 3 line echo "New content" >&3 exec 3>&-

实际应用示例

日志处理

bash
# 分离正常输出和错误输出 ./script.sh 1> success.log 2> error.log # 合并日志 ./script.sh > all.log 2>&1 # 实时监控日志 tail -f /var/log/app.log | grep --line-buffered "ERROR" | tee errors.log

数据处理

bash
# 处理 CSV 文件 cat data.csv | cut -d, -f1,3 | sort -u > output.txt # 统计信息 cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn > stats.txt # 批量处理 find . -name "*.txt" -exec cat {} \; | grep "pattern" > results.txt

系统管理

bash
# 备份重要命令输出 df -h > disk_usage_$(date +%Y%m%d).txt ps aux > process_list_$(date +%Y%m%d).txt # 监控系统 while true; do date >> monitor.log free -m >> monitor.log echo "---" >> monitor.log sleep 60 done

脚本开发

bash
# 捕获命令输出 result=$(command) echo "Result: $result" # 处理多行输出 while IFS= read -r line; do echo "Processing: $line" done < <(find . -name "*.sh") # 创建临时文件 tmpfile=$(mktemp) command > "$tmpfile" # 处理文件 rm -f "$tmpfile"

最佳实践

  1. 使用 /dev/null 丢弃不需要的输出: 减少日志噪音
  2. 分别处理 stdout 和 stderr: 便于调试和日志分析
  3. 使用管道组合命令: 提高处理效率
  4. 使用 tee 同时输出和保存: 便于实时监控
  5. 注意管道的缓冲: 使用 --line-buffered 处理实时数据
  6. 使用进程替换: 避免创建临时文件
  7. 及时关闭文件描述符: 防止资源泄漏
  8. 使用 mktemp 创建临时文件: 避免文件名冲突
标签:Shell