read
コマンドは、標準入力から 1行の入力を読み取り、変数に格納 するためのシェル組み込みコマンドです。
対話的にユーザー入力を受け付けたり、スクリプト内で入力値を処理する際に利用されます。
構文(Syntax)
read [オプション] [変数...]
主なオプション一覧
オプション | 説明 | 使用例 |
---|---|---|
(なし) | 入力を1行読み取り、指定した変数に格納 | read name |
-p "PROMPT" | 入力前にメッセージを表示 | read -p "Enter your name: " name |
-s | 入力を非表示(パスワード入力向け) | read -s password |
-t N | 入力を待つ秒数を指定(タイムアウト) | read -t 5 name |
-n N | N文字だけ読み取る | read -n 1 key |
-r | バックスラッシュをエスケープ文字として扱わない | read -r line |
-a ARRAY | 入力を配列に格納 | read -a items |
-d DELIM | 区切り文字を指定(デフォルトは改行) | read -d : input |
実行例
基本的な入力の読み取り
read name
echo "Hello, $name"
実行例:
Alice ← ユーザー入力
Hello, Alice
プロンプト付きで入力
read -p "Enter your name: " name
echo "Welcome, $name"
パスワードを非表示で入力
read -s -p "Password: " password
echo
echo "Password entered (hidden)"
5秒以内に入力がなければタイムアウト
read -t 5 -p "Enter your name: " name
1文字だけ入力を取得
read -n 1 -p "Press any key: " key
echo "You pressed '$key'"
改行やエスケープをそのまま読み取る
read -r line
配列として入力を格納
read -a items
echo "First item: ${items[0]}"
入力例:
apple banana cherry
出力例:
First item: apple
区切り文字(:)までを入力として取得
echo "abc:def:ghi" | read -d : var
echo "$var"
出力例:
abc
エラー例(タイムアウト)
read -t 2 name
出力例:
(2秒経過後に終了、変数は空)
csvファイルの取り扱い
read
コマンドを使うことでcsvファイルに記載された情報による処理の繰り返し実行に対応できます。
1) 基本:カンマ区切り(引用・カンマ埋め込みなし想定)
#!/usr/bin/env bash
# basic_csv_read.sh
# 例: ./basic_csv_read.sh sample.csv
set -o errexit -o nounset -o pipefail
csv_file="${1:-sample.csv}"
# ヘッダーを読み飛ばしたいときは tail -n +2 を使う
tail -n +2 "$csv_file" | while IFS=, read -r id name age; do
# 空行スキップ
[[ -z "${id}${name}${age}" ]] && continue
printf 'id=%s, name=%s, age=%s\n' "$id" "$name" "$age"
done
- 前提:
"Alice, Bob"
のようなフィールド内カンマや二重引用符が無いCSV向け。
2) 可変列数を配列で受ける(列数がバラつくCSV向け)
#!/usr/bin/env bash
# csv_to_array.sh
# 例: ./csv_to_array.sh sample.csv
set -o errexit -o nounset -o pipefail
csv_file="${1:-sample.csv}"
# ヘッダー飛ばし
{ read -r _header; cat; } < "$csv_file" | \
while IFS=, read -r -a cols; do
[[ ${#cols[@]} -eq 0 ]] && continue
echo "列数=${#cols[@]} / 先頭=${cols[0]}"
# 例: 3列目を安全に参照
if (( ${#cols[@]} >= 3 )); then
echo "3列目=${cols[2]}"
fi
done
read -a
で配列に展開できます(ただし引用・埋め込みカンマは未対応)。
3) RFC4180 風:ダブルクォート対応(埋め込みカンマ・二重の二重引用符 “” を扱う)
Bash だけで素朴にパースする小さな関数。改行を含むフィールドは未対応ですが、一般的な
"a, b","x""y"
を処理できます。
#!/usr/bin/env bash
# csv_read_rfcish.sh
# 例: ./csv_read_rfcish.sh sample_quoted.csv
set -o errexit -o nounset -o pipefail
csv_read_line() { # usage: csv_read_line array_name ; reads 1 logical line from stdin
local __arr_name=$1
local line
IFS= read -r line || return 1
local -a fields=()
local field="" c next in_quotes=0
local i=0 len=${#line}
while (( i < len )); do
c=${line:i:1}
if (( in_quotes )); then
if [[ $c == '"' ]]; then
next=${line:i+1:1}
if [[ $next == '"' ]]; then
field+='"' # 連続する "" はエスケープされた "
((i++))
else
in_quotes=0 # クォート終了
fi
else
field+="$c"
fi
else
case "$c" in
'"') in_quotes=1 ;; # クォート開始
',') fields+=("$field"); field="" ;;
$'\r') ;; # CR 無視(Windows 改行対策)
*) field+="$c" ;;
esac
fi
((i++))
done
fields+=("$field")
# nameref 経由で呼び出し側の配列に代入(bash 4.3+)
local -n __ref=$__arr_name
__ref=("${fields[@]}")
return 0
}
csv_file="${1:-sample_quoted.csv}"
# ヘッダーを先に1行読む(必要なければ削除)
{
IFS= read -r header || true
echo "HEADER: $header"
while csv_read_line cols; do
# 空行スキップ
[[ ${#cols[@]} -eq 1 && -z ${cols[0]} ]] && continue
printf 'Row:'
for ((i=0; i<${#cols[@]}; i++)); do
printf ' [%d]=<%s>' "$i" "${cols[$i]}"
done
printf '\n'
done
} < "$csv_file"
テスト用 sample_quoted.csv
id,name,comment
1,"Alice","Hello, world"
2,"Bob","He said ""Good luck!"" yesterday"
3,"Carol","no quotes"
4) CSVを書き出す(値を安全にエスケープして出力)
#!/usr/bin/env bash
# csv_write.sh
# 例: ./csv_write.sh > out.csv
set -o errexit -o nounset -o pipefail
csv_escape() {
local s=$1
s=${s//\"/\"\"} # " を "" に
if [[ "$s" == *[,\"$'\n'$'\r']* ]]; then
printf '"%s"' "$s"
else
printf '%s' "$s"
fi
}
# 見出し
printf '%s,%s,%s\n' "id" "name" "note"
# データ例
id=1; name='Alice'; note='Hello, world'
printf '%s,%s,%s\n' \
"$(csv_escape "$id")" \
"$(csv_escape "$name")" \
"$(csv_escape "$note")"
id=2; name='Bob'; note='He said "Good luck!"'
printf '%s,%s,%s\n' \
"$(csv_escape "$id")" \
"$(csv_escape "$name")" \
"$(csv_escape "$note")"
補足(実務Tips)
- 行末
\r
が混ざるCSV(Windows由来)は、読み取り時にread -r
しつつ上の実装のように\r
を無視するか、事前にdos2unix
等で正規化すると安定します。 - 完全なCSV互換(改行入りフィールドなど)を厳密にやるなら、
mlr
,awk(FPAT)
,python -c 'import csv'
などの専用パーサを併用するのが安全です。
関連コマンド
echo
: 変数やメッセージの出力printf
: 書式付きの出力select
: シェル組み込み、メニュー形式で選択を受け付け
備考
read
は多くのシェル(bash, zsh, ksh, dash)において シェル組み込み コマンドです。read
で指定した変数は、そのシェルの環境でのみ有効。外部コマンドではありません。- パスワード入力のように非表示にする場合は
-s
を利用しますが、シェルの種類によって挙動が異なる場合があります。
参考
- manページ(bash組込み): man7.org bash(1)
- GNU Bash Reference Manual: https://www.gnu.org/software/bash/manual/
コメント