Unix/Linux 的 read 指令使用
read 用於從標準輸入或檔案中讀取資料。
常用參數
-r
: 不解析反斜線為轉義字元-p <提示文字>
: 顯示提示訊息-s
: 隱藏輸入內容-t <秒數>
: 設定輸入等待的秒數,超時則結束-n <字元數>
: 限定最多讀取的字元數-d <字元>
: 指定輸入終止字元-a <變數名>
: 將輸入以空白分割,存入陣列變數
常用範例
讀取多個變數
# 讀取多個變數
read -p "請輸入姓名和年齡: " name age
echo "姓名: $name, 年齡: $age"
# 讀取陣列
read -a colors -p "請輸入幾種顏色(用空格分隔): "
echo "第一個顏色: ${colors[0]}"
echo "所有顏色: ${colors[@]}"
指定分隔符號
使用 IFS 環境變數可以設定分隔符號,並且交給 read 讀取:
# 兩者相同
echo "owner_name/repo_name" | IFS='/' read -r owner repo
IFS='/' read -r owner repo <<< owner_name/repo_name
意思是設定臨時的環境變數 IFS 指定以 /
分隔字串。
因為 shell 全都是字串處理,所以除了使用 IFS 以外也有很多不同方式可以完成,比如說也可以用 tr
或者 awk
來完成,但就會非常麻煩:
其他方式
# tr
read -r owner repo <<< "$(tr '/' ' ' <<< owner_name/repo_name)"
# cut + tr
read -r owner repo <<< "$(echo owner_name/repo_name | cut -d'/' -f1,2 | tr '/' ' ')"
# awk
read -r owner repo <<< "$(echo owner_name/repo_name | awk -F/ '{print $1, $2}')"
# set
set -- owner_name/repo_name; owner=${1%/*} repo=${1#*/}
讀取檔案
處理檔案內容我整理為以下幾種使用方式
# 逐行讀取檔案
while read line; do
echo "處理行: $line"
done < file.txt
# 逐行讀取檔案到陣列中(僅適用於 bash 4.0+)
mapfile -t lines < file.txt
for line in "${lines[@]}"; do
echo "$line"
done
# 逐行讀取檔案到陣列中,不使用 mapfile
lines=()
while IFS= read -r line; do
lines+=("$line")
done < file.txt
for line in "${lines[@]}"; do
echo "$line"
done
# 讀取整個檔案,有多種方式,第一種效率最高
content=$(<file.txt)
content=$(cat file.txt)
# CSV 檔案處理
while IFS=, read name age city; do
echo "姓名: $name, 年齡: $age, 城市: $city"
done < data.csv
設定條件
控制使用者輸入的方式或設定特定條件:
# 隱藏輸入內容
read -s -p "請輸入密碼: " password
echo -e "\n密碼長度: ${#password}"
# 設定輸入時限
read -t 5 -p "請在5秒內輸入你的名字: " name
echo "你好,$name"
# 限制輸入字元數
read -n 1 -p "請按任意鍵繼續..." key
echo -e "\n你按了: $key"
限制輸入
限制只能輸入 yes/no
yes_no_prompt() {
local prompt="$1"
local response
while true; do
read -p "$prompt (y/n): " response
case "$response" in
[Yy]|[Yy][Ee][Ss]) return 0 ;;
[Nn]|[Nn][Oo]) return 1 ;;
*) echo "請只輸入 yes/y 或 no/n" ;;
esac
done
}
if yes_no_prompt "是否要刪除此檔案"; then
echo "開始刪除檔案..."
else
echo "已取消操作"
fi