はじめに#
こんにちは!今回はshiftコマンドについて解説します。
shiftは、位置パラメータ($1, $2, $3…)を左にずらすコマンドです。スクリプトで複数の引数を順番に処理したい時に使います。
shiftコマンドとは#
shiftは、位置パラメータを左にシフトする組み込みコマンドです。
例えば、shiftを実行すると、$2が$1になり、$3が$2になり…という感じで全部が1つ左にずれます。元の$1は消えます。これを使うと、引数を1つずつ処理していけます。
基本構文#
使用例#
例1: 基本的なshift#
1
2
3
4
5
6
7
8
9
10
11
|
#!/bin/bash
echo "第1引数: $1"
echo "第2引数: $2"
echo "第3引数: $3"
shift
echo "shift後の第1引数: $1"
echo "shift後の第2引数: $2"
echo "shift後の第3引数: $3"
|
実行:
1
|
./script.sh apple banana orange
|
実行結果:
1
2
3
4
5
6
|
第1引数: apple
第2引数: banana
第3引数: orange
shift後の第1引数: banana
shift後の第2引数: orange
shift後の第3引数:
|
appleが消えて、全部が1つ左にずれました。
例2: ループで全引数を処理#
1
2
3
4
5
6
|
#!/bin/bash
while [ $# -gt 0 ]; do
echo "処理中: $1"
shift
done
|
実行:
1
|
./script.sh file1.txt file2.txt file3.txt
|
実行結果:
1
2
3
|
処理中: file1.txt
処理中: file2.txt
処理中: file3.txt
|
$#は引数の数なので、これが0より大きい間ループします。
例3: 複数シフト#
1
2
3
4
5
6
7
8
9
|
#!/bin/bash
echo "最初の3つの引数:"
echo "$1 $2 $3"
shift 3 # 3つ分シフト
echo "shift 3 後:"
echo "$1 $2 $3"
|
実行:
1
|
./script.sh a b c d e f
|
実行結果:
1
2
3
4
|
最初の3つの引数:
a b c
shift 3 後:
d e f
|
数値を指定すると、その数だけシフトできます。
例4: オプション解析#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#!/bin/bash
VERBOSE=false
OUTPUT=""
while [ $# -gt 0 ]; do
case "$1" in
-v|--verbose)
VERBOSE=true
shift
;;
-o|--output)
OUTPUT="$2"
shift 2 # オプションと値の2つをシフト
;;
*)
echo "不明なオプション: $1"
exit 1
;;
esac
done
echo "Verbose: $VERBOSE"
echo "Output: $OUTPUT"
|
実行:
1
|
./script.sh -v -o result.txt
|
実行結果:
1
2
|
Verbose: true
Output: result.txt
|
オプション解析で超よく使います。
例5: 引数の数をカウント#
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
echo "引数の数: $#"
count=0
while [ $# -gt 0 ]; do
count=$((count + 1))
echo "${count}番目: $1"
shift
done
echo "合計: $count 個"
|
実行:
1
|
./script.sh apple banana orange
|
実行結果:
1
2
3
4
5
|
引数の数: 3
1番目: apple
2番目: banana
3番目: orange
合計: 3 個
|
例6: 最初の引数を特別扱い#
1
2
3
4
5
6
7
8
9
10
11
|
#!/bin/bash
COMMAND=$1
shift # コマンドを取り出してシフト
echo "コマンド: $COMMAND"
echo "残りの引数:"
for arg in "$@"; do
echo " - $arg"
done
|
実行:
1
|
./script.sh install package1 package2 package3
|
実行結果:
1
2
3
4
5
|
コマンド: install
残りの引数:
- package1
- package2
- package3
|
最初の引数をコマンドとして扱って、残りをオプションとして処理するパターン。
例7: shiftのエラーチェック#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Error: 引数が足りません"
exit 1
fi
NAME=$1
shift
AGE=$1
shift
echo "名前: $NAME"
echo "年齢: $AGE"
echo "その他: $@"
|
実行:
1
|
./script.sh Taro 25 Tokyo Japan
|
実行結果:
1
2
3
|
名前: Taro
年齢: 25
その他: Tokyo Japan
|
例8: shift不可能な場合#
1
2
3
4
5
6
7
8
9
10
11
|
#!/bin/bash
echo "引数の数: $#"
shift 10 # 引数が10個ない場合
if [ $? -ne 0 ]; then
echo "shiftに失敗しました"
else
echo "shiftに成功"
fi
|
実行:
実行結果:
shiftする数より引数が少ないとエラーになります。
Tips・注意点#
-
$@と$*の違い: shiftはどちらにも影響する
1
2
|
shift
echo "$@" # shift後の引数
|
-
引数の数($#)は自動更新: shiftすると$#も減る
1
2
3
|
echo "Before: $#"
shift
echo "After: $#"
|
-
元に戻せない: shiftした引数は復元できない
1
2
3
|
FIRST=$1 # 保存しておく
shift
# $1はもう戻せない
|
-
空の時にshiftするとエラー: 引数がない時の対策が必要
1
2
3
|
if [ $# -gt 0 ]; then
shift
fi
|
-
関数内でも使える: 関数の引数もshiftできる
1
2
3
4
5
|
my_func() {
echo "First: $1"
shift
echo "Rest: $@"
}
|
実践的な使い方#
コマンドラインオプションの解析#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#!/bin/bash
# デフォルト値
INPUT=""
OUTPUT=""
VERBOSE=false
# ヘルプメッセージ
show_help() {
echo "使い方: $0 -i INPUT -o OUTPUT [-v]"
echo " -i INPUT 入力ファイル"
echo " -o OUTPUT 出力ファイル"
echo " -v 詳細モード"
}
# オプション解析
while [ $# -gt 0 ]; do
case "$1" in
-i|--input)
INPUT="$2"
shift 2
;;
-o|--output)
OUTPUT="$2"
shift 2
;;
-v|--verbose)
VERBOSE=true
shift
;;
-h|--help)
show_help
exit 0
;;
*)
echo "Error: 不明なオプション $1"
show_help
exit 1
;;
esac
done
# 必須パラメータのチェック
if [ -z "$INPUT" ] || [ -z "$OUTPUT" ]; then
echo "Error: 入力ファイルと出力ファイルは必須です"
show_help
exit 1
fi
echo "入力: $INPUT"
echo "出力: $OUTPUT"
echo "詳細モード: $VERBOSE"
|
複数ファイルの処理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Error: ファイルを指定してください"
exit 1
fi
count=0
while [ $# -gt 0 ]; do
file="$1"
if [ -f "$file" ]; then
echo "処理中: $file"
# ファイル処理
wc -l "$file"
count=$((count + 1))
else
echo "Warning: $file が見つかりません"
fi
shift
done
echo "合計 $count ファイル処理しました"
|
サブコマンドの実装#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#!/bin/bash
SCRIPT_NAME=$(basename "$0")
# サブコマンド: start
cmd_start() {
echo "Starting service..."
# 起動処理
}
# サブコマンド: stop
cmd_stop() {
echo "Stopping service..."
# 停止処理
}
# サブコマンド: restart
cmd_restart() {
cmd_stop
cmd_start
}
# メイン処理
if [ $# -eq 0 ]; then
echo "使い方: $SCRIPT_NAME {start|stop|restart}"
exit 1
fi
COMMAND=$1
shift # コマンド名を取り出してシフト
case "$COMMAND" in
start)
cmd_start "$@"
;;
stop)
cmd_stop "$@"
;;
restart)
cmd_restart "$@"
;;
*)
echo "Error: 不明なコマンド: $COMMAND"
exit 1
;;
esac
|
引数のグループ処理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/bin/bash
# ペアで処理(キーと値)
while [ $# -gt 0 ]; do
key="$1"
value="$2"
if [ $# -lt 2 ]; then
echo "Error: $key に対応する値がありません"
exit 1
fi
echo "設定: $key = $value"
shift 2 # 2つずつシフト
done
|
実行:
1
|
./script.sh name Taro age 25 city Tokyo
|
リストの最初と残り#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Error: 引数が必要です"
exit 1
fi
first=$1
shift
echo "最初の要素: $first"
if [ $# -gt 0 ]; then
echo "残りの要素:"
for item in "$@"; do
echo " - $item"
done
else
echo "残りの要素はありません"
fi
|
まとめ#
今回はshiftコマンドについて解説しました。
ポイント:
shiftで位置パラメータを左にシフトできる
- 引数を1つずつ処理するループでよく使う
shift nで複数個シフト可能
- オプション解析の実装に便利
- $#(引数の数)は自動的に減る
- shiftした引数は元に戻せない
シェルスクリプトでコマンドラインオプションを処理する時には、shiftが必須です。whileループと組み合わせて、柔軟なオプション解析を実装してみてください。
次回もLinuxコマンドの学習を続けていきましょう!