読者です 読者をやめる 読者になる 読者になる

harry’s memorandum

おれおれメモ

Bashの変数パラメータ展開のまとめ

Bashのパラメータ展開はすぐに忘れてしまうのでメモ。

変数の文字数

${#parameter}で変数の文字数を調べることができます。

name=/var/log/boot.log
echo ${#name}
17

wcやawkコマンドを使う方法がありますがスマートではありません。*1

$ n=`echo $name | wc -c`; echo $(($n-1))
17
$ echo $name | awk '{ print length($0)}'
17

配列も同じように配列数を調べることができます。

$ array=(a b c d e)
$ echo ${array[0]}
a
$ echo ${#array[@]}
5

変数パラメータ展開

変数を切り出せます。ファイル名やディレクトリ名を簡単に切り出すことができます。

$ name=/var/log/boot.log
$ echo ${name##*/}
boot.log

色々な方法があります。

パラメータ展開 内容
${parameter#word} 先頭から前方最短一致した位置まで取り除きます
${parameter##word} 先頭から前方最長一致した位置まで取り除きます
${parameter%word} 末尾から後方最短一致した位置まで取り除きます
${parameter%%word} 末尾から後方最長一致した位置まで取り除きます

実行結果をずらずら並べてみる。

$ name=/var/log/boot.log
$ echo ${name#*/}
var/log/boot.log
$ echo ${name##*/} #=> ファイル名を取得
boot.log
$ echo ${name%*/}
/var/log/boot.log
$ echo ${name%/*}  #=> ディレクトリ名を取得
/var/log
$ echo ${name%%/*}

$ echo ${name%.*} #=> 拡張子を削除
/var/log/boot
$ echo ${name##*.} #=> 拡張子を取得
log
$ echo ${name##/var/} #=> 先頭の/var/を削除
log/boot.log

ブレース展開

ブレースを使うと短縮表現することができます。/bin/ls と /bin/ln はこのように書くことができます。

$ echo  /bin/l{s,n}
/bin/ls /bin/ln
$ ls -l /bin/l{s,n}
-rwxr-xr-x 1 root root 27276  525  2008 /bin/ln
-rwxr-xr-x 1 root root 89464  525  2008 /bin/ls 

ブレース展開はファイルの存在は必要ありません。

$ echo /{s,}bin/{a,b,c,d,e}
/sbin/a /sbin/b /sbin/c /sbin/d /sbin/e /bin/a /bin/b /bin/c /bin/d /bin/e

アスタリスクを付けると、シェルが先にアスタリスクを展開するため存在するファイルをみつけてくれます。

$ echo /{s,}bin/{a,gr*}
/sbin/a /sbin/grub /sbin/grub-install /sbin/grub-md5-crypt /sbin/grub-terminfo
 /sbin/grubby /bin/a /bin/grep

引数を2つ使うコマンドにはサフィックスを付けてブレース展開すると非常に便利になります。

$ echo testing.rb{,.backup}
testing.rb testing.rb.backup

ブレース展開を利用して日付毎にバックアップ

$ cp -p testing.rb{,.`date +%Y%m%d`}
$ ls testing.rb{,.`date +%Y%m%d`}
testing.rb  testing.rb.20090211

ブレース展開を利用して一括でファイルをリネーム

$ ls
audit2allow     autoconf    automake      automake-1.6  autoreconf
authconfig      autoheader  automake-1.4  automake-1.7  autoscan
authconfig-tui  autom4te    automake-1.5  automake-1.9  autoupdate
$ for i in *; do mv $i{,.bak}; done
$ ls
audit2allow.bak     autoconf.bak    automake-1.4.bak  automake-1.7.bak  autoreconf.bak
authconfig-tui.bak  autoheader.bak  automake-1.5.bak  automake-1.9.bak  autoscan.bak
authconfig.bak      autom4te.bak    automake-1.6.bak  automake.bak      autoupdate.bak

*1:wcは改行までカウントするので-1する必要があります