0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[シェル] 位置パラメータを配列のように扱う

Last updated at Posted at 2024-08-03

参考「3.4.1 Positional Parameters - Bash Reference Manual
参考「3.4.2 Special Parameters - Bash Reference Manual
参考「3.5.3 Shell Parameter Expansion - Bash Reference Manual

1. 取得

参考「[シェル] 特殊パラメータ @ のパラメータ展開 - Qiita

1.1. 全て

特殊パラメータを用いて全ての位置パラメータを取得することが出来ます。

コード 意味
$# 位置パラメータの数
"$@" 全ての位置パラメータをそれぞれ展開
"$*" 全ての位置パラメータを展開して連結

ちなみに、パラメータ展開 "${parameter@Q}" を用いて文字列をエスケープすることが出来ます。

# 
function length() {
	echo "$#"
}

# 
function f() {

	echo "$#"

	echo "$@"
	length "$@"
	echo "${@@Q}"
	length "${@@Q}"

	echo "$*"
	length "$*"
	echo "${*@Q}"
	length "${*@Q}"

}

f foo bar baz
例の実行結果
3
foo bar baz
3
'foo' 'bar' 'baz'
3
foo bar baz
1
'foo' 'bar' 'baz'
1

1.2. 単独

位置が定数の場合、"$1""${12}" のようにして取得します。

他に間接展開や部分列を用いて単独の位置パラメータを取得する方法があります。

コード 意味
"$1" 最初の位置パラメータ
"${!offset}" $offset 番目の位置パラメータ
"${@:$#}"
"${@: -1}"
最後の位置パラメータ
# 
function f() {

	echo "$1"
	# echo "$12" # 間違い
	echo "${12}"

}

f \'p1\' \'p2\' \'p3\' \'p4\' \'p5\' \'p6\' \'p7\' \'p8\' \'p9\' \'p10\' \'p11\' \'p12\'

# 
function g() {

	local -ri offset=2
	echo "${!offset}"

}

g foo bar baz

# 
function h() {

	echo "${@:$#}"
	echo "${@: -1}"

	local -ri offset_last=$#
	echo "${!offset_last}"

}

h foo bar baz
例の実行結果
'p1'
'p12'
bar
baz
baz
baz

間接展開 "${!#}" に関しては、Bash で POSIX モードを無効化している場合に使用可能です。

set -o posix

# 
function f() {

	# echo "${!#}" # エラー発生

	set +o posix
	echo "${!#}"
	set -o posix

}

f foo bar baz
例の実行結果
baz

1.3. 部分列

使い方
"${@:offset}"
"${@:offset:length}"

特殊パラメータ @ の場合、offset に負の数を指定することは出来ますが、length に負の数を指定することは出来ません。

部分列の終端を末尾からのオフセットで指定したい場合は、特殊パラメータ $# を用いて計算します。

# 
function f() {

	echo "${@:2}"

	echo "${@: -3}"
	# echo "${@:-3}" # 間違い

	local -ri offset=2
	echo "${@:offset}"

}

f foo bar baz qux

# 
function g() {

	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 foo bar baz qux
例の実行結果
bar baz qux
bar baz qux
bar baz qux
bar baz
bar baz
bar baz
bar baz

他に以下のような部分列の使い方があります。

部分列を含むコード 意味
"${@:1}" $@
"$1" "${@:2}" 最初の位置パラメータを分割
"${@:1:$#-1}" "${@:$#}"
"${@:1:$#-1}" "${@: -1}"
最後の位置パラメータを分割
# 
function f() {

	echo "${@:1}"
	echo "$@"

	echo "$1" '|' "${@:2}"

	echo "${@:1:$#-1}" '|' "${@:$#}"
	echo "${@:1:$#-1}" '|' "${@: -1}"

}

f foo bar baz
例の実行結果
foo bar baz
foo bar baz
foo | bar baz
foo bar | baz
foo bar | baz

1.4. ループ

ループを用いて位置パラメータをそれぞれ取得することが出来ます。

参考「3.2.5.1 Looping Constructs - Bash Reference Manual

# 
function f() {

	for p; do
		echo -n "$p "
	done
	echo

	local -i i
	for (( i = 1; i <= $#; i++ )); do
		echo -n "${!i} "
	done
	unset i
	echo

}

f foo bar baz

# 
function g() {

	local -i i=1
	while test $i -le $#; do
		echo -n "${!i} "
		let i++
	done
	unset i
	echo

	local -i i=1
	while [ $i -le $# ]; do
		echo -n "${!i} "
		let i++
	done
	unset i
	echo

	local -i i=1
	while [[ i -le $# ]]; do
		echo -n "${!i} "
		let i++
	done
	unset i
	echo

	local -i i=1
	while (( i <= $# )); do
		echo -n "${!i} "
		let i++
	done
	unset i
	echo

}

g foo bar baz
例の実行結果
foo bar baz
foo bar baz
foo bar baz
foo bar baz
foo bar baz
foo bar baz

2. 設定

通常の代入文では位置パラメータの値を変更できませんが、set コマンドを使用することで全ての位置パラメータを置き換えることができます。

参考「set - Bash Reference Manual

set -- foo bar baz
echo "$@"

set -- FOO BAR BAZ
echo "$@"
例の実行結果
foo bar baz
FOO BAR BAZ

3. 追加

set コマンドで "$@" を使用することで、前後に位置パラメータを追加することが出来ます。

3.1. 先頭

set -- foo bar
echo "$@"
set -- baz "$@"
echo "$@"

set -- foo bar
echo "$@"
set -- baz qux "$@"
echo "$@"
例の実行結果
foo bar
baz foo bar
foo bar
baz qux foo bar

3.2. 末尾

set -- foo bar
echo "$@"
set -- "$@" baz
echo "$@"

set -- foo bar
echo "$@"
set -- "$@" baz qux
echo "$@"
例の実行結果
foo bar
foo bar baz
foo bar
foo bar baz qux

4. 削除

4.1. 先頭

先頭の位置パラメータを削除する場合、shift コマンドを使用します。

参考「shift - Bash Reference Manual

set -- foo bar baz qux
echo "$@"
shift
echo "$@"

set -- foo bar baz qux
echo "$@"
shift 2
echo "$@"
例の実行結果
foo bar baz qux
bar baz qux
foo bar baz qux
baz qux

4.2. 末尾

末尾の位置パラメータを削除する場合、部分列を取得し set コマンドで全ての位置パラメータを置き換えます。

set -- foo bar baz qux
echo "$@"
set -- "${@:1:$#-1}"
echo "$@"

set -- foo bar baz qux
echo "$@"
set -- "${@:1:$#-2}"
echo "$@"
例の実行結果
foo bar baz qux
foo bar baz
foo bar baz qux
foo bar

4.3. ループ

ループを用いて位置パラメータをそれぞれ取得しながら削除することが出来ます。

参考「3.2.5.1 Looping Constructs - Bash Reference Manual

set -- foo bar baz
while test $# -gt 0; do
	echo -n "$1 "
	shift
done
echo

set -- foo bar baz
while [ $# -gt 0 ]; do
	echo -n "$1 "
	shift
done
echo

set -- foo bar baz
while [[ $# -gt 0 ]]; do
	echo -n "$1 "
	shift
done
echo

set -- foo bar baz
while (( $# > 0 )); do
	echo -n "$1 "
	shift
done
echo
例の実行結果
foo bar baz
foo bar baz
foo bar baz
foo bar baz

5. 変換

5.1. 部分列

部分列を取得し set コマンドで全ての位置パラメータを置き換えることで、部分列の位置パラメータを変換することが出来ます。

# 
function command_qux() {
	echo 'qux'
}

# 
set -- foo bar baz
echo "$@"
set -- "$(command_qux "$1")" "${@:2}"
echo "$@"

set -- foo bar baz
echo "$@"
set -- "${@:1:$#-1}" "$(command_qux "${@:$#}")"
echo "$@"

set -- foo bar baz
echo "$@"
set -- "${@:1:$#-1}" "$(command_qux "${@: -1}")"
echo "$@"
例の実行結果
foo bar baz
qux bar baz
foo bar baz
foo bar qux
foo bar baz
foo bar qux

5.2. 全て

一部のパラメータ展開は特殊パラメータ @ に対して使うと各位置パラメータに適用されます。

参考「[シェル] 特殊パラメータ @ のパラメータ展開 - Qiita

set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@#* }"
echo "${@##* }"
echo "${@% *}"
echo "${@%% *}"

set -- 'foo bar baz' 'foo bar baz' 'foo bar baz'
echo "${@/ /_}"
echo "${@// /_}"
echo "${@/#foo/***}"
echo "${@/%baz/***}"

set -- foo bar baz
echo "${@^}"
echo "${@^^}"
echo "${@^f}"
echo "${@^^a}"

set -- FOO BAR BAZ
echo "${@,}"
echo "${@,,}"
echo "${@,F}"
echo "${@,,A}"

set -- foo '\' \'
echo "${@@Q}"
例の実行結果
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 foo_bar_baz foo_bar_baz
*** bar baz *** bar baz *** bar baz
foo bar *** foo bar *** foo bar ***
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' '\' \'
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?