シェルにおいて、同じパラメータ展開でもパラメータの種類が特殊パラメータか配列か等によって動作が異なる場合があります。
本記事では、特殊パラメータ @
の場合のパラメータ展開の挙動についてまとめます。
0. まとめ
説明 | コード |
@ に適用 |
各位置パラメータに適用 |
---|---|---|---|
デフォルト値 | "${@:-word}" |
✓ | |
エラー表示 |
"${@:?}" "${@:?word}"
|
✓ | |
代替値 | "${@:+word}" |
✓ | |
部分列 |
"${@:offset}" "${@:offset:length}"
|
✓ | |
長さ |
$# ${#@}
|
✓ | |
パターン削除 |
"${@#pattern}" "${@##pattern}" "${@%pattern}" "${@%%pattern}"
|
✓ | |
パターン置換 |
"${@/pattern/string}" "${@//pattern/string}" "${@/#pattern/string}" "${@/%pattern/string}" "${@/pattern}" "${@//pattern}" "${@/#pattern}" "${@/%pattern}"
|
✓ | |
大文字小文字変換 |
"${@^}" "${@^^}" "${@^pattern}" "${@^^pattern}" "${@,}" "${@,,}" "${@,pattern}" "${@,,pattern}"
|
✓ | |
変換 | "${@@operator}" |
✓ |
※パラメータ展開 ${parameter:=word}
は特殊パラメータに対して使用不可。
※各パラメータ展開の詳細は man bash
等を参照。
参考「3.5.3 Shell Parameter Expansion - Bash Reference Manual」
1. デフォルト値
"${@:-word}"
#
function f() {
set -- foo bar baz
echo "${@:-qux}"
set -- foo bar ''
echo "${@:-qux}"
set --
echo "${@:-qux}"
set -- ''
echo "${@:-qux}"
}
f
#
function g() {
local -r word='qux'
set -- foo bar baz
echo "${@:-$word}"
set -- foo bar ''
echo "${@:-$word}"
set --
echo "${@:-$word}"
set -- ''
echo "${@:-$word}"
}
g
foo bar baz
foo bar
qux
qux
foo bar baz
foo bar
qux
qux
2. エラー表示
"${@:?}"
"${@:?word}"
#
function f() {
set -- foo bar baz
echo "${@:?}"
set -- foo bar ''
echo "${@:?}"
set --
# echo "${@:?}" # エラー発生
set -- ''
# echo "${@:?}" # エラー発生
}
f
#
function g() {
set -- foo bar baz
echo "${@:?qux}"
set -- foo bar ''
echo "${@:?qux}"
set --
# echo "${@:?qux}" # エラー発生
set -- ''
# echo "${@:?qux}" # エラー発生
}
g
#
function h() {
local -r word='qux'
set -- foo bar baz
echo "${@:?$word}"
set -- foo bar ''
echo "${@:?$word}"
set --
# echo "${@:?$word}" # エラー発生
set -- ''
# echo "${@:?$word}" # エラー発生
}
h
foo bar baz
foo bar
foo bar baz
foo bar
foo bar baz
foo bar
3. 代替値
"${@:+word}"
#
function f() {
set -- foo bar baz
echo "${@:+qux}"
set -- foo bar ''
echo "${@:+qux}"
set --
echo "${@:+qux}"
set -- ''
echo "${@:+qux}"
}
f
#
function g() {
local -r word='qux'
set -- foo bar baz
echo "${@:+$word}"
set -- foo bar ''
echo "${@:+$word}"
set --
echo "${@:+$word}"
set -- ''
echo "${@:+$word}"
}
g
qux
qux
qux
qux
4. 部分列
特殊パラメータ @
自体は配列でないですが、パラメータ展開の部分列は配列と同様に特殊パラメータ @
に対しても使用することができます。
"${@:offset}"
"${@:offset:length}"
特殊パラメータ @
の場合、offset
に負の数を指定することは出来ますが、length
に負の数を指定することは出来ません。
部分列の終端を末尾からのオフセットで指定したい場合は、特殊パラメータ $#
を用いて計算します。
#
function f() {
set -- foo bar baz qux
echo "${@:2}"
echo "${@: -3}"
# echo "${@:-3}" # 間違い
local -ri offset=2
echo "${@:offset}"
}
f
#
function g() {
set -- foo bar baz qux
echo "${@:2:2}"
echo "${@: -3:2}"
# echo "${@:-3:2}" # 間違い
echo "${@:2:$#-2}"
# echo "${@:2:-1}" # エラー発生
local -ri offset=2
local -ri length=2
echo "${@:offset:length}"
}
g
bar baz qux
bar baz qux
bar baz qux
bar baz
bar baz
bar baz
bar baz
他に以下のような部分列の使い方があります。
部分列 | 意味 |
---|---|
"${@:0:1}" |
シェルまたはシェルスクリプトの名前"$0"
|
"${@:1:1}" |
最初の位置パラメータ"$1"
|
"${@:offset:1}" |
$offset 番目の位置パラメータ"${!offset}"
|
"${@:$#}" "${@: -1}"
|
最後の位置パラメータ (※書き換えは後述) |
"${@:0}" |
"$0" "$@" |
"${@:1}" |
"$@" |
#
function f() {
set -- foo bar baz
echo "${@:0:1}"
echo "$0"
echo "${@:1:1}"
echo "$1"
local -ri offset=2
echo "${@:offset:1}"
echo "${!offset}"
echo "${@:$#}"
echo "${@: -1}"
}
f
#
function g() {
set -- foo bar baz
echo "${@:0}"
echo "$0" "$@"
echo "${@:1}"
echo "$@"
}
g
./name.sh
./name.sh
foo
foo
bar
bar
baz
baz
./name.sh foo bar baz
./name.sh foo bar baz
foo bar baz
foo bar baz
5. 長さ
パラメータ展開 ${#parameter}
を用いて ${#@}
とすることで位置パラメータの数を取得できますが、特殊パラメータ $#
の値と等しくなるため $#
を使って問題ないと思います。
$#
${#@}
set -- foo bar baz
echo "$# ${#@}"
set -- 'foo bar baz'
echo "$# ${#@}"
set --
echo "$# ${#@}"
set -- ''
echo "$# ${#@}"
set -- foo bar ''
echo "$# ${#@}"
3 3
1 1
0 0
1 1
3 3
6. パターン削除
"${@#pattern}"
"${@##pattern}"
"${@%pattern}"
"${@%%pattern}"
パターンに関しては別記事にしました。
set -- 'foo bar baz'
echo "${@#* }"
echo "${@##* }"
echo "${@% *}"
echo "${@%% *}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@#* }"
echo "${@##* }"
echo "${@% *}"
echo "${@%% *}"
set -- foo bar baz
echo "${@#* }"
echo "${@##* }"
echo "${@% *}"
echo "${@%% *}"
bar baz
baz
foo bar
foo
bar baz bar baz bar baz
baz baz baz
foo bar foo bar foo bar
foo foo foo
foo bar baz
foo bar baz
foo bar baz
foo bar baz
7. パターン置換
"${@/pattern/string}"
"${@//pattern/string}"
"${@/#pattern/string}"
"${@/%pattern/string}"
"${@/pattern}"
"${@//pattern}"
"${@/#pattern}"
"${@/%pattern}"
パターンに関しては別記事にしました。
set -- 'foo bar baz'
echo "${@/ /_}"
echo "${@// /_}"
echo "${@/#foo/***}"
echo "${@/%baz/***}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@/ /_}"
echo "${@// /_}"
echo "${@/#foo/***}"
echo "${@/%baz/***}"
set -- foo bar baz
echo "${@/ /_}"
echo "${@// /_}"
echo "${@/#foo/***}"
echo "${@/%baz/***}"
foo_bar baz
foo_bar_baz
*** bar baz
foo bar ***
foo_bar baz foo_bar baz foo_bar baz
foo_bar_baz foo_bar_baz foo_bar_baz
*** bar baz *** bar baz *** bar baz
foo bar *** foo bar *** foo bar ***
foo bar baz
foo bar baz
*** bar baz
foo bar ***
set -- 'foo bar baz'
echo "${@/ }"
echo "${@// }"
echo "${@/#* }"
echo "${@/% *}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@/ }"
echo "${@// }"
echo "${@/#* }"
echo "${@/% *}"
set -- foo bar baz
echo "${@/ }"
echo "${@// }"
echo "${@/#* }"
echo "${@/% *}"
foobar baz
foobarbaz
baz
foo
foobar baz foobar baz foobar baz
foobarbaz foobarbaz foobarbaz
baz baz baz
foo foo foo
foo bar baz
foo bar baz
foo bar baz
foo bar baz
8. 大文字小文字変換
8.1. 大文字へ変換
"${@^}"
"${@^^}"
"${@^pattern}"
"${@^^pattern}"
パターンに関しては別記事にしました。
set -- foo bar baz
echo "${@^}"
echo "${@^^}"
echo "${@^f}"
echo "${@^^a}"
set -- 'foo bar baz'
echo "${@^}"
echo "${@^^}"
echo "${@^f}"
echo "${@^^a}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@^}"
echo "${@^^}"
echo "${@^f}"
echo "${@^^a}"
Foo Bar Baz
FOO BAR BAZ
Foo bar baz
foo bAr bAz
Foo bar baz
FOO BAR BAZ
Foo bar baz
foo bAr bAz
Foo bar baz Foo bar baz Foo bar baz
FOO BAR BAZ FOO BAR BAZ FOO BAR BAZ
Foo bar baz Foo bar baz Foo bar baz
foo bAr bAz foo bAr bAz foo bAr bAz
8.2. 小文字へ変換
"${@,}"
"${@,,}"
"${@,pattern}"
"${@,,pattern}"
パターンに関しては別記事にしました。
set -- FOO BAR BAZ
echo "${@,}"
echo "${@,,}"
echo "${@,F}"
echo "${@,,A}"
set -- 'FOO BAR BAZ'
echo "${@,}"
echo "${@,,}"
echo "${@,F}"
echo "${@,,A}"
set -- 'FOO BAR BAZ' 'FOO BAR BAZ' 'FOO BAR BAZ'
echo "${@,}"
echo "${@,,}"
echo "${@,F}"
echo "${@,,A}"
fOO bAR bAZ
foo bar baz
fOO BAR BAZ
FOO BaR BaZ
fOO BAR BAZ
foo bar baz
fOO BAR BAZ
FOO BaR BaZ
fOO BAR BAZ fOO BAR BAZ fOO BAR BAZ
foo bar baz foo bar baz foo bar baz
fOO BAR BAZ fOO BAR BAZ fOO BAR BAZ
FOO BaR BaZ FOO BaR BaZ FOO BaR BaZ
9. 変換
"${@@operator}"
9.1. 大文字小文字変換
変換 | 意味 |
---|---|
"${@@U}" |
大文字へ変換"${@^^}"
|
"${@@u}" |
最初の文字を大文字へ変換"${@^}"
|
"${@@L}" |
小文字へ変換"${@,,}"
|
#
function f() {
set -- foo bar baz
echo "${@@U}"
echo "${@^^}"
set -- 'foo bar baz'
echo "${@@U}"
echo "${@^^}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@@U}"
echo "${@^^}"
}
f
#
function g() {
set -- foo bar baz
echo "${@@u}"
echo "${@^}"
set -- 'foo bar baz'
echo "${@@u}"
echo "${@^}"
set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@@u}"
echo "${@^}"
}
g
#
function h() {
set -- FOO BAR BAZ
echo "${@@L}"
echo "${@,,}"
set -- 'FOO BAR BAZ'
echo "${@@L}"
echo "${@,,}"
set -- 'FOO BAR BAZ' 'FOO BAR BAZ' 'FOO BAR BAZ'
echo "${@@L}"
echo "${@,,}"
}
h
FOO BAR BAZ
FOO BAR BAZ
FOO BAR BAZ
FOO BAR BAZ
FOO BAR BAZ FOO BAR BAZ FOO BAR BAZ
FOO BAR BAZ FOO BAR BAZ FOO BAR BAZ
Foo Bar Baz
Foo Bar Baz
Foo bar baz
Foo bar baz
Foo bar baz Foo bar baz Foo bar baz
Foo bar baz Foo bar baz Foo bar baz
foo bar baz
foo bar baz
foo bar baz
foo bar baz
foo bar baz foo bar baz foo bar baz
foo bar baz foo bar baz foo bar baz
9.2. エスケープ関連
変換 | 意味 |
---|---|
"${@@Q}" |
エスケープ |
"${@@E}" |
バックスラッシュエスケープを展開 |
"${@@P}" |
プロンプト文字列として展開 |
"${@@A}" |
位置パラメータの値を割り当てる set コマンドに変換 |
※パラメータ展開 "${@@a}"
は空文字列になります (特殊パラメータの変数属性は変更出来ないため) 。
※パラメータ展開 "${@@K}"
および "${@@k}"
は "${@@Q}"
と同じ結果になります (特殊パラメータ @
は配列でなく、位置パラメータに配列を設定することも出来ないため) 。
set -- foo '\' \'
echo "${@@Q}"
set -- foo '\\' '\'\'
echo "${@@E}"
set -- '\'s '\'v
echo "${@@P}"
set -- foo '\' \'
echo "${@@A}"
'foo' '\' \'
foo \ '
bash 5.2
set -- 'foo' '\' \'
10. おまけ: 位置パラメータの間接展開
間接展開で位置パラメータを扱うことができます。
"${!offset}"
#
function f() {
set -- foo bar baz
local -ri offset=2
echo "${!offset}"
echo "${@:offset:1}"
local -ri offset_last=$#
echo "${!offset_last}"
echo "${@:$#}"
echo "${@: -1}"
}
f
bar
bar
baz
baz
baz
間接展開 "${!#}"
に関しては、Bash で POSIX モードを無効化している場合に使用可能です。
set -o posix
#
function f() {
set -- foo bar baz
# echo "${!#}" # エラー発生
set +o posix
echo "${!#}"
set -o posix
echo "${@:$#}"
echo "${@: -1}"
}
f
baz
baz
baz