Bash
Bashパラメータの拡張
サーチ…
前書き
$
文字は、パラメータ展開、コマンド置換、または算術展開を導入します。展開されるパラメータ名またはシンボルは、省略可能な中括弧で囲むことができますが、名前の一部として解釈できる直後の文字から展開する変数を保護する役割を果たします。
Bashユーザーマニュアルを読んでください。
構文
- $ {parameter:offset}#オフセットから始まる部分文字列
- $ {parameter:offset:length}#オフセットから始まる長さ "length"の部分文字列
- $ {#parameter}#パラメータの長さ
- $ {parameter / pattern / string}#パターンの最初のオカレンスをstringに置き換えます
- $ {parameter // pattern / string}#すべてのパターンをstringに置き換えます
- $ {parameter /#pattern / string}#パターンが冒頭にある場合、patternをstringに置き換えます
- $ {parameter /%pattern / string}#パターンが終わりにある場合、patternをstringに置き換えます
- $ {parameter#pattern}#パラメータの先頭からパターンの最短一致を削除する
- $ {parameter ## pattern}#パターンの最長一致をパラメータの先頭から削除する
- $ {parameter%pattern}#パラメータの最後からパターンの最短一致を削除する
- $ {parameter %% pattern}#パターンの最長一致をパラメータの終わりから削除する
- $ {parameter:-word}#パラメータをunset / undefinedにすると、単語に展開されます。
- $ {parameter:= word}#パラメータをunset / undefinedにしてパラメータを設定すると、単語に展開されます
- $ {parameter:+ word}#パラメータが設定/定義されている場合は、単語に展開する
サブストリングとサブアレイ
var='0123456789abcdef'
# Define a zero-based offset
$ printf '%s\n' "${var:3}"
3456789abcdef
# Offset and length of substring
$ printf '%s\n' "${var:3:4}"
3456
# Negative length counts from the end of the string
$ printf '%s\n' "${var:3:-5}"
3456789a
# Negative offset counts from the end
# Needs a space to avoid confusion with ${var:-6}
$ printf '%s\n' "${var: -6}"
abcdef
# Alternative: parentheses
$ printf '%s\n' "${var:(-6)}"
abcdef
# Negative offset and negative length
$ printf '%s\n' "${var: -6:-5}"
a
パラメータが位置パラメータまたは添え字付き配列の要素である場合、同じ展開が適用されます。
# Set positional parameter $1
set -- 0123456789abcdef
# Define offset
$ printf '%s\n' "${1:5}"
56789abcdef
# Assign to array element
myarr[0]='0123456789abcdef'
# Define offset and length
$ printf '%s\n' "${myarr[0]:7:3}"
789
オフセットは1ベースの位置パラメータにも同様の拡張が適用されます 。
# Set positional parameters $1, $2, ...
$ set -- 1 2 3 4 5 6 7 8 9 0 a b c d e f
# Define an offset (beware $0 (not a positional parameter)
# is being considered here as well)
$ printf '%s\n' "${@:10}"
0
a
b
c
d
e
f
# Define an offset and a length
$ printf '%s\n' "${@:10:3}"
0
a
b
# No negative lengths allowed for positional parameters
$ printf '%s\n' "${@:10:-2}"
bash: -2: substring expression < 0
# Negative offset counts from the end
# Needs a space to avoid confusion with ${@:-10:2}
$ printf '%s\n' "${@: -10:2}"
7
8
# ${@:0} is $0 which is not otherwise a positional parameters or part
# of $@
$ printf '%s\n' "${@:0:2}"
/usr/bin/bash
1
サブストリングの展開は、 インデックス付き配列で使用できます 。
# Create array (zero-based indices)
$ myarr=(0 1 2 3 4 5 6 7 8 9 a b c d e f)
# Elements with index 5 and higher
$ printf '%s\n' "${myarr[@]:12}"
c
d
e
f
# 3 elements, starting with index 5
$ printf '%s\n' "${myarr[@]:5:3}"
5
6
7
# The last element of the array
$ printf '%s\n' "${myarr[@]: -1}"
f
パラメータの長さ
# Length of a string
$ var='12345'
$ echo "${#var}"
5
これは、 文字数の長さであり、必ずしもバイト数 (大部分の文字が2バイト以上でエンコードされているUTF-8のようなもの)やグリフ/グラフェムの数(いくつかは文字の組み合わせ)、また、表示幅と必ずしも同じではありません。
# Number of array elements
$ myarr=(1 2 3)
$ echo "${#myarr[@]}"
3
# Works for positional parameters as well
$ set -- 1 2 3 4
$ echo "${#@}"
4
# But more commonly (and portably to other shells), one would use
$ echo "$#"
4
アルファベット文字の大文字と小文字の変更
大文字にする
$ v="hello"
# Just the first character
$ printf '%s\n' "${v^}"
Hello
# All characters
$ printf '%s\n' "${v^^}"
HELLO
# Alternative
$ v="hello world"
$ declare -u string="$v"
$ echo "$string"
HELLO WORLD
小文字にする
$ v="BYE"
# Just the first character
$ printf '%s\n' "${v,}"
bYE
# All characters
$ printf '%s\n' "${v,,}"
bye
# Alternative
$ v="HELLO WORLD"
$ declare -l string="$v"
$ echo "$string"
hello world
トグルケース
$ v="Hello World"
# All chars
$ echo "${v~~}"
hELLO wORLD
$ echo "${v~}"
# Just the first char
hello World
パラメータインダイレクション
Bash
インダイレクションでは、名前が別の変数に含まれている変数の値を取得できます。変数例:
$ red="the color red"
$ green="the color green"
$ color=red
$ echo "${!color}"
the color red
$ color=green
$ echo "${!color}"
the color green
間接的な拡張の使用法を示すいくつかの例:
$ foo=10
$ x=foo
$ echo ${x} #Classic variable print
foo
$ foo=10
$ x=foo
$ echo ${!x} #Indirect expansion
10
もう1つの例:
$ argtester () { for (( i=1; i<="$#"; i++ )); do echo "${i}";done; }; argtester -ab -cd -ef
1 #i expanded to 1
2 #i expanded to 2
3 #i expanded to 3
$ argtester () { for (( i=1; i<="$#"; i++ )); do echo "${!i}";done; }; argtester -ab -cd -ef
-ab # i=1 --> expanded to $1 ---> expanded to first argument sent to function
-cd # i=2 --> expanded to $2 ---> expanded to second argument sent to function
-ef # i=3 --> expanded to $3 ---> expanded to third argument sent to function
デフォルト値置換
${parameter:-word}
パラメータが設定されていないか、またはnullの場合、単語の展開が置換されます。それ以外の場合は、parameterの値が代入されます。
$ unset var
$ echo "${var:-XX}" # Parameter is unset -> expansion XX occurs
XX
$ var="" # Parameter is null -> expansion XX occurs
$ echo "${var:-XX}"
XX
$ var=23 # Parameter is not null -> original expansion occurs
$ echo "${var:-XX}"
23
${parameter:=word}
parameterが設定されていないかnullの場合、wordの展開はパラメータに代入されます。その後、パラメータの値が代入されます。このようにして位置パラメータと特殊パラメータを割り当てることはできません。
$ unset var
$ echo "${var:=XX}" # Parameter is unset -> word is assigned to XX
XX
$ echo "$var"
XX
$ var="" # Parameter is null -> word is assigned to XX
$ echo "${var:=XX}"
XX
$ echo "$var"
XX
$ var=23 # Parameter is not null -> no assignment occurs
$ echo "${var:=XX}"
23
$ echo "$var"
23
変数が空または設定されていない場合はエラー
このセマンティクスはデフォルト値の置換と同様ですが、デフォルト値を代用する代わりに、提供されたエラーメッセージでエラーが発生します。フォームは${VARNAME?ERRMSG}
と${VARNAME:?ERRMSG}
です。持つフォームは:
変数が未設定 または 空の場合は、変数が設定されていない場合のないフォームにのみ出てエラーになるのに対し、私たちがエラーになります。エラーがスローされると、 ERRMSG
が出力され、終了コードが1
設定されます。
#!/bin/bash
FOO=
# ./script.sh: line 4: FOO: EMPTY
echo "FOO is ${FOO:?EMPTY}"
# FOO is
echo "FOO is ${FOO?UNSET}"
# ./script.sh: line 8: BAR: EMPTY
echo "BAR is ${BAR:?EMPTY}"
# ./script.sh: line 10: BAR: UNSET
echo "BAR is ${BAR?UNSET}"
エラーのあるechoステートメントの上にある完全な例を実行すると、処理を続行するためにコメントアウトする必要があります。
文字列の先頭からパターンを削除する
最短一致:
$ a='I am a string'
$ echo "${a#*a}"
m a string
最長一致:
$ echo "${a##*a}"
string
文字列の最後からパターンを削除する
最短一致:
$ a='I am a string'
$ echo "${a%a*}"
I am
最長一致:
$ echo "${a%%a*}"
I
文字列のパターンを置き換える
最初の試合:
$ a='I am a string'
$ echo "${a/a/A}"
I Am a string
すべての試合:
$ echo "${a//a/A}"
I Am A string
最初の試合:
$ echo "${a/#I/y}"
y am a string
最後に一致:
$ echo "${a/%g/N}"
I am a strinN
パターンを何も置き換えない:
$ echo "${a/g/}"
I am a strin
配列項目に接頭辞を追加する:
$ A=(hello world)
$ echo "${A[@]/#/R}"
Rhello Rworld
拡張時のマングング
変数は必ずしもその値に展開する必要はありません。拡張子は、ファイル拡張子やパスの一部を抽出するのに便利です。グロブ文字は通常の意味を持ちますので、 .*
はリテラルドットを指し、その後に文字列が続きます。それは正規表現ではありません。
$ v=foo-bar-baz
$ echo ${v%%-*}
foo
$ echo ${v%-*}
foo-bar
$ echo ${v##*-}
baz
$ echo ${v#*-}
bar-baz
デフォルト値を使って変数を展開することもできます。たとえば、ユーザーのエディタを呼び出すとしますが、変数を設定していない場合は、それらをvim
に渡します。
$ EDITOR=nano
$ ${EDITOR:-vim} /tmp/some_file
# opens nano
$ unset EDITOR
$ $ ${EDITOR:-vim} /tmp/some_file
# opens vim
この拡張を実行するには、関連する変数が空であるか、または設定されていないかによって異なる2つの方法があります。使用すると、 :-
変数が未設定または空のどちらかであるならば一方で、デフォルトを使用します-
唯一の変数が設定されていない場合は、デフォルトを使用しますが、それは空の文字列に設定されている場合、変数を使用します。
$ a="set"
$ b=""
$ unset c
$ echo ${a:-default_a} ${b:-default_b} ${c:-default_c}
set default_b default_c
$ echo ${a-default_a} ${b-default_b} ${c-default_c}
set default_c
デフォルトと同様に、代替案を与えることができます。特定の変数が使用できない場合にデフォルトが使用される場合、その変数が使用可能である場合に代替が使用されます。
$ a="set"
$ b=""
$ echo ${a:+alternative_a} ${b:+alternative_b}
alternative_a
これらの展開をネストすることができることに留意して、コマンドラインフラグに引数を渡すときには、選択肢を使用すると特に便利になります。
$ output_file=/tmp/foo
$ wget ${output_file:+"-o ${output_file}"} www.stackexchange.com
# expands to wget -o /tmp/foo www.stackexchange.com
$ unset output_file
$ wget ${output_file:+"-o ${output_file}"} www.stackexchange.com
# expands to wget www.stackexchange.com
パラメータ展開とファイル名
Bash Parameter Expansionを使用して、 basename
やdirname
などの一般的なファイル名処理操作をエミュレートできます。
これを例のパスとして使用します:
FILENAME="/tmp/example/myfile.txt"
dirname
をエミュレートし、ファイルパスのディレクトリ名を返すには:
echo "${FILENAME%/*}"
#Out: /tmp/example
basename $FILENAME
をエミュレートし、ファイルパスのファイル名を返すには:
echo "${FILENAME##*/}"
#Out: myfile.txt
basename $FILENAME .txt
をエミュレートして、 .txt.
ずにファイル名を返し.txt.
拡張:
BASENAME="${FILENAME##*/}"
echo "${BASENAME%%.txt}"
#Out: myfile