シェル変数の中にさらに変数を入れる(sh、bash系)

対象:sh、bash

eval を使いシェル変数の中に変数を入れる

たまに変数の中に変数を入れたくなる場面に遭遇します。その”たまに”がどんな場面だったのか記憶に無いのですが、とにかく過去にはあったので記録します。



サンプルコード variable_name.sh

#!/bin/sh


##### 変数名自体を変数に入れる
# 最終的に参照したい変数名
x=xxx
y=yyy

# 変数名を入れる変数
Vname=x

# 変数 x が参照される
echo 1 '$'$Vname
eval echo 2 '$'$Vname


Vname=y

# 変数 y が参照される
echo 3 '$'$Vname
eval echo 4 '$'$Vname

$Vname と言う変数の中にさらに変数名を入れています。10行目と17行目です。

echo で単純に参照した場合と、eval で変数を展開して参照した場合を比較して出力しています。実行結果は、下記を見てください。

実行結果

% variable_name.sh
1 $x
2 xxx
3 $y
4 yyy

eval を使うことによって、ちゃんと変数の中に変数が入っていることがわかりますね。

csh、tcsh 系は、↓↓↓ こちらにあります。ほとんど同じですがご覧ください。

シェル変数の中にさらに変数を入れる(csh、tcsh系)


200×200 高速大容量レンタルサーバ10G
mixhost

シェル変数の中にさらに変数を入れる(csh、tcsh系)

対象:csh、tcsh

eval を使いCシェル変数の中に変数を入れる

たまに変数の中に変数を入れたくなる場面に遭遇します。その”たまに”がどんな場面だったのか記憶に無いのですが、とにかく過去にはあったので記録します。



サンプルコード variable_name.csh

#!/bin/csh


##### 変数名自体を変数に入れる
# 最終的に参照したい変数名
set x = xxx
set y = yyy

# 変数名を入れる変数
set Vname = x

# 変数 x が参照される
echo 1 '$'$Vname
eval echo 2 '$'$Vname


set Vname = y

# 変数 y が参照される
echo 3 '$'$Vname
eval echo 4 '$'$Vname

$Vname と言う変数の中にさらに変数名を入れています。10行目と17行目です。

echo で単純に参照した場合と、eval で変数を展開して参照した場合を比較して出力しています。実行結果は、下記を見てください。

実行結果

% variable_name.csh
1 $x
2 xxx
3 $y
4 yyy

eval を使うことによって、ちゃんと変数の中に変数が入っていることがわかりますね。

sh、bash 系は、↓↓↓ こちらにあります。ほとんど同じですがご覧ください。

シェル変数の中にさらに変数を入れる(sh、bash系)

200×200 高速大容量レンタルサーバ10G
mixhost

日付/時刻のゼロサプレス

対象:csh、tcsh

Cシェルの日付計算ジ時の0の扱い

dateコマンドで日付や時刻を取得した場合、ゼロ付きというかゼロで先頭を埋めて返ってくるものがあります。man dateを見てください。

       %H     hour (00..23)

       %I     hour (01..12)

       %j     day of year (001..366)

       %k     hour ( 0..23)

       %l     hour ( 1..12)

       %m     month (01..12)

       %M     minute (00..59)

       %S     second (00..60)


抜粋したものを載せました。

時などは、%H の代わりに %k を使うなどすれば良いのですが、分や秒はどうしても0が付く場合があります。0が付いたままシェルの中で計算するとエラーになる場合があります。下記に例を示します。

% @ b = 8 + 1
% echo $b
9

% @ b = 08 + 1
@: 番号が正しい書式になっていません.

例では 8 と 08 で比較していますが、二桁であればうまく動いてしまいます。

そこで、先頭から続く0を考慮する必要があります。やり方としては2つあります。サンプルにあるように @を 使いたい場合と、@ をやめる方法です。

200×200 高速大容量レンタルサーバ10G
mixhost

“日付/時刻のゼロサプレス” の続きを読む

シェルのデバッグ(sh、bash系)

対象:sh、bash

シェル(sh、bash系)のデバッグは alias を利用する

前回紹介したcsh、tcsh系に続いて、sh、bash系です。

シェルのデバッグ(csh、tcsh系)

私は、csh や tcsh 系を得意としていますが、世の中sh系を得意とする方もいるので、考えてみました。考え方や内容はほぼ一緒です。微妙な違いと言えば、function を一部使っていたり、alias の有効化みたいなおまじないが違います。function を使わずに alias だけでうまく作れるかもしれませんが、思いつきませんでした。あと、せっかくデバッグなので、シェルの行番号を出すように Decho の第一引数に $LINENO を付けています。これを alias の中に入れてしまいたかったのですが、うまくいかずに現状諦めてます。$LINENO は、csh、tcsh には無いので前回のサンプルには組み込んでいません。

200×200 高速大容量レンタルサーバ10G
mixhost

sh、bash の場合のサンプルコード debug.sh

#!/bin/sh

# alias を有効化
shopt -s expand_aliases

# ログファイル名
# debug.log は適当なパスを記述する
export DLOG=debug.log

# デフォルトでは、デバッグログを出力しない設定
alias Decho=':'
alias Dprintf=':'
alias DechoOFF="alias Decho=':'"
alias DprintfOFF="alias Dprintf=':'"
alias DebugOFF="DechoOFF;DprintfOFF"

function DechoF() { echo $* >> $DLOG ;}
function DprintfF() { F=$1;shift;printf "$F" $* >> $DLOG ;}
# デバッグ出力をログファイル($LOG)に出力するなら2行目を有効にする
alias DechoON="alias Decho='echo'"
#alias DechoON="alias Decho='DechoF'"
alias DprintfON="alias Dprintf='printf'"
#alias DprintfON="alias Dprintf='DprintfF'"
alias DebugON="DechoON;DprintfON"


##### 以下は動作確認

# 出力されない
Decho $LINENO 1 2 3
Dprintf "%d %s %s %s\n" $LINENO a b c

# 出力される
# Decho、Dprintf を個別にONにする
DechoON
Decho $LINENO 2 2 3
DprintfON
Dprintf "%d %s %s %s\n" $LINENO b b c

# 出力されない
# Decho、Dprintf を個別にOFFにする
DechoOFF
Decho $LINENO 3 2 3
DprintfOFF
Dprintf "%d %s %s %s\n" $LINENO c b c

# 出力される
# Decho、Dprintf を一括でONにする
DebugON
Decho $LINENO 4 2 3
Dprintf "%d %s %s %s\n" $LINENO d b c

# 出力されない
# Decho、Dprintf を一括でOFFにする
DebugOFF
Decho $LINENO 5 2 3
Dprintf "%d %s %s %s\n" $LINENO e b c

実行結果

% debug.sh
36 2 2 3
38 b b c
50 4 2 3
51 d b c

いかがでしょうか、簡単に出力する/しないも切り替えが可能ですし、ソース行番号も表示されてりと、デバッグが楽になると思います。




シェルのデバッグ(csh、tcsh系)

対象:csh、tcsh

シェル(csh、tcsh系)のデバッグは alias を利用する

シェルにはデバッガーがあるわけではないので、デバッグにはちょっとコツがいります。-x オプションを指定して、実行ラインを標準エラーに出しながら行うことも可能ですが、本来のスクリプトの出力とごっちゃになってわけがわからなくなる場合もあります。簡単なスクリプトなら、それでも大丈夫でしょうが。

私の場合、デバッグプリントと言う古典的な手法を用いますが、echo や printf でただ単に出力させると、デバッグ完了後の本番時には、その echo 文などを削除するかコメントアウトする必要があり、それもまた手間がかかります。

そこで、echo や printf の代わりにデバッグ専用の Decho、Dprintf を別名定義や関数化してスクリプトに埋め込み使っています。まずは、サンプルコードを見てください。

“シェルのデバッグ(csh、tcsh系)” の続きを読む