echo 是 Shell 腳本中最常用的輸出命令,但其行為因 Shell 類型、參數、轉義序列不同而有細微差異。本文系統總結重定向覆蓋/追加、轉義解析、格式化輸出、以及跨 Shell 兼容性最佳實踐。
# 覆蓋寫入(截斷文件) echo "內容" > file.txt # 等效於 printf "%s\n" "內容" > file.txt # 追加寫入(文件末尾添加) echo "內容" >> file.txt # 等效於 printf "%s\n" "內容" >> file.txt # 關鍵差異 echo "第一行" > test.txt echo "第二行" > test.txt # 文件僅剩「第二行」 echo "第三行" >> test.txt # 文件變為「第二行\n第三行」
# 默認行為:不同 Shell 不同 # bash/zsh: 默認不解析轉義(需 -e) # dash/sh: 可能默認解析 echo "Line1\nLine2" # 輸出字面字符串:Line1\nLine2 echo -e "Line1\nLine2" # 輸出兩行(解析 \n) echo -E "Line1\nLine2" # 強制不解析(bash 默認) # 常用轉義序列 \a 響鈴 \b 退格 \c 抑制結尾換行符 \f 換頁 \n 換行 \r 回車 \t 水平製表符 \v 垂直製表符 \\ 反斜杠 \0nnn 八進制字符 \xhh 十六進制字符
# 方法 1:-n 參數(bash/zsh/ksh 支援,POSIX 未標準化) echo -n "無換行輸出" # 方法 2:\c 轉義(需 -e,POSIX 標準) echo -e "無換行輸出\c" # 方法 3:printf(最可移植、推薦) printf "無換行輸出" printf "%s" "格式化%s輸出" "內容"
var="Hello World" # 兩個空格 echo $var # 輸出:Hello World(多空格壓縮為一個,通配符展開風險) echo "$var" # 輸出:Hello World(保留原始空格,安全) echo '$var' # 輸出:$var(單引號不展開變量) # 命令替換 echo "Today: $(date)" # 推薦:$() 可巢狀、可讀性強 echo "Today: `date`" # 反引號:舊語法,難以巢狀
由於 echo 行為在不同 Shell(bash/dash/zsh/ksh)、不同 Unix 系統間不一致,複雜格式化場景強制使用 printf:
最佳實踐總結
- 簡單字符串輸出:
echo "msg"可接受,但建議統一printf "%s\n" "msg"。- 變量輸出:永遠雙引號包裹
echo "$var"。- 重定向:覆蓋用
>,追加用>>,區分明確。- 轉義/格式化/抑制換行:直接用
printf,避免echo -e/-n兼容性坑。- 腳本首行聲明:
#!/bin/bash明確使用 bash,減少 dash/sh 差異。兼容性測試腳本
#!/bin/bash # test_echo.sh echo "=== echo 行為測試 ===" echo "1. 字面 \n 測試:"; echo "a\nb" echo "2. -e 解析 \n:"; echo -e "a\nb" echo "3. -n 抑制換行:"; echo -n "no newline"; echo " <- after" echo "4. 變量空格保留:"; v="x y"; echo "無引號:$v"; echo "雙引號:\"$v\"" echo "5. 命令替換:"; echo "Date: $(date +%F)"