echo:打印
echo "hello"
echo "name: $name"
echo -n "no newline" # 不加结尾换行
echo -e "tab:\tnewline:\n" # 启用转义
printf:更精确的打印(推荐)
printf "name: %s age: %d\n" "alice" 30
printf "pi = %.4f\n" 3.14159265
printf "%-10s %s\n" "Name:" "Alice" # %-10s = 左对齐 10 宽
printf "%5d\n" 42 # %5d = 右对齐 5 宽
# 多次套用一组格式
printf "%-10s %s\n" Name Alice Age 30 City NY
# Name Alice
# Age 30
# City NY
printf 行为统一(不像 echo 在不同 shell 有差异),写正经脚本优先 printf。
read:读用户输入
read -p "你叫啥?" name
echo "你好 $name"
read -s -p "密码:" pwd # -s 不回显
echo
echo "密码长度:${#pwd}"
# 设默认值
read -p "端口 [80]:" port
port=${port:-80} # 空就用 80
重定向
# 标准输入:fd 0
# 标准输出:fd 1
# 标准错误:fd 2
cmd > file # stdout 写文件(覆盖)
cmd >> file # stdout 追加
cmd 2> err.txt # stderr 写文件
cmd > out.txt 2> err.txt # 分开
cmd > all.txt 2>&1 # stderr 合并到 stdout
cmd &> all.txt # 简写(bash 4+)
cmd > /dev/null # 丢掉 stdout
cmd 2> /dev/null # 丢掉 stderr
cmd &> /dev/null # 全丢
cmd < input.txt # 从文件读 stdin
cmd <<< "hello" # here string:把字符串当 stdin
cmd <<EOF # here doc:多行
line 1
line 2
EOF
管道 | —— 上一个的 stdout → 下一个的 stdin
ls -l | grep ".txt" | sort | head -5
把 stderr 也送进管道:
cmd 2>&1 | grep error
bash 4+ 简写:
cmd |& grep error
tee:管道里写文件(同时屏幕也看)
ls -l | tee out.txt # 屏幕和文件都出
ls -l | tee -a out.txt # 追加
cmd | tee out.txt | grep foo # 中间存一份
实战:长命令要看输出又要存档:
make 2>&1 | tee build.log
here doc:多行字符串
cat <<EOF
第 1 行
第 2 行 $name
EOF
写文件:
cat <<EOF > config.ini
[server]
port = 8080
host = $HOST
EOF
不展开变量(保持字面):
cat <<'EOF' > literal.txt
这里 $name 不会被展开
EOF
实战:脚本日志双写
#!/bin/bash
exec > >(tee -a /var/log/myapp.log) 2>&1
echo "脚本启动 $(date)"
# ... 任何后续输出都同时进日志和屏幕
下一篇:条件判断。