ラベル Shell の投稿を表示しています。 すべての投稿を表示
ラベル Shell の投稿を表示しています。 すべての投稿を表示

2013/05/03

シェルで乱数を扱う

私はシェル上で乱数をあまり使うことはないのですが、そもそもUNIX機を中心に使っていた時代には簡単に扱えませんでした。シェル上で乱数を扱うには実は2つの方法があります。1つはLinuxでbashを前提とした環境依存の方法です。もう1つの方法はシェルに依存しない方法です。

シェル変数RANDOM

まずはbash上でのみ利用できる方法です。前段にてLinuxという条件を記載しましたが、シェルスクリプトを実装する際は、/bin/shで動くことを前提に通常は実装すると思いますのでLinuxを前提という条件を加えています。ご存知の方も多いと思いますが、Linxuでは/bin/shはbashのシンボリックリンクになっている点に基づいています。
bashでは、シェル変数としてRANDOMが容易されています。このRANDOM変数には0~32767までの整数がランダムに格納されます。実行例は以下の通りです。

 $ echo $RANDOM
 31129
 foo=$RANDOM
 ech $foo
 25999
シェル変数を利用するだけなので、非常に簡単に乱数を扱えるのがお分かり頂けたかと思います。

乱数疑似デバイスファイル

続いてはシェルに依存しない方法を紹介します。
疑似デバイスファイル(/dev/nullなどのことです。)の中に/dev/randomがあります。これを利用して乱数を生成します。この疑似デバイスファイルを使って乱数を生成するには、odコマンドを利用します。od(Octal Dump)コマンドはファイルや標準入力のデータを 8進数・10進数・16進数で表示するコマンドです。デフォルトは 8進数ダンプでダンプを行います。実行例は以下の通りです。

 $ od -An -N4 -tu$ 
odコマンドのオプションをいくつか指定しています。まず桁数についてですが、「-N」オプションが入力のバイト数、「-t」が出力のバイト数をそれぞれ指定しています。これらオプションに続く数値は合わせておく必要があります。なお、-N4以上を指定しても残念ながら桁数をふやすことはできないので注意して下さい。また「-t」オプションに続く「u」はunsigned decimalです。
「-A」オプションは表示するオフセットの基数を指定するオプションです。dが10進数、oが8進数、xが16進数、nがオフセット非表示を表します。乱数を取得したいのでオフセットを表示する必要はないため「n」を指定しています。

2013/05/02

コマンドラインでの移動制御

CUI環境でシェルが提供する移動制御機能を扱います。前提とするシェルは、Linux標準のbashです。
移動制御ですが、これはカーソルの移動制御のことです。bashでは初期状態でキー・バインディングが設定されていて、キー操作によるカーソルの移動制御を行うことができます。今では十字キーでカーソル動かしている方を多々見かけますが、キー操作で制御した方が早くて楽です。
主なキー操作は下表の通りです。

キー操作 移動制御動作
Ctrl+f カーソルを右に移動します。
Ctrl+b カーソルを左に移動します。
Ctrl+d カーソル位置の文字を削除します。
Ctrl+a カーソルを行の先頭に移動します。
Ctrl+b カーソルを行の末尾に移動します。
Ctrl+k カーソル位置から行の末尾までの文字を削除します。
Ctrl+u カーソル位置から行の先頭までの文字を削除します。
Ctrl+w カーソル行の直前のワードを削除します。
Ctrl+l カーソル行より上をクリアします。
Esc+f カーソルを直後のワードに移動します。
Esc+b カーソルを直前のワードに移動します。
Esc+d カーソル位置からワードの末尾までを削除します。

2013/05/01

Linuxの/bin/sh

概要

Linuxの/bin/shはBourneシェルかと思いきや、実はBashへのシンボリックリンクになっています。Bashはshの上位互換のシェルなので基本的には問題ないらしいです。ちなみにshとして起動した場合は、sh互換モードというモードで起動するようです。

 $ ls -l `which sh`

 lrwxrwxrwx. 1 root root 4 10月  8 12:04 2012 /bin/sh -> bash

sh互換モード

bashのsh互換モードについての説明です。

シェルオプションの違い

bashで起動した場合とshで起動した場合のシェルオプションを比較してみます。

$ sh
$ set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           on
privileged      off
verbose         off
vi              off
xtrace          off

$ bash
$ set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off

上記の結果を見ると分かると思いますが、shで起動した場合シェルオプションの25行目の「posix」が有効になっているのが分かります。このオプションの有効/無効の違いによってbashがBourneシェルに近い動作をするように切り替えています。

2013/04/25

Shell変数

基礎

シェル変数の特徴的な部分は、定義と参照で表記が変わる点です。
定義の際は、「変数=値」といったスタイルで記載しますが、参照の際は、「${変数}」という形で変数を表記します。
もう一つ定義する際は、「=」と変数、値の間は連続している必要があります。スペースなどを間に入れてしまうとエラーになるので注意が必要です。

位置パラメータ

シェルスクリプトで引数を利用するときに必要な概念です。
スクリプト実行時に渡された引数は、位置パラメータという特殊な変数を通して参照します。
位置パラメータは、ドル記号「$」とそれに続く数字1文字で構成されます。$1 $2 $3 ・・・といったスタイルで、数字の部分が引数の位置を表します。
数字1文字と書きましたが、これでは9個までしか引数を受け取れないということになってしまいます。9個以上の引数を扱いたい場合は、「shift」コマンドを利用します。shiftコマンドを実行すると位置パラメータが参照する引数がずれる、つまり$1が第2引数、$2が第3引数を参照するといった具合です。
例えば、以下の内容でtest.shを作成し、実行してみると動きがわかります。

#!/bin/sh

while [ 0 -le $# ]
do
  echo $1
  shift
done
実行すると10個以上の引数をshiftコマンドを使って参照をずらし$1で順番に参照できているのが分かります。
$ sh test.sh a b c d e f g h i j k l m
a
b
c
d
e
f
g
h
i
j
k
l
なお、「$#」は引数の数が可能される特殊変数の一種です。 では、test.shを以下の通り変更するとどうなるか見てみましょう。
#!/bin/sh

while [ 0 -le $# ]
do
  echo $1
  shift 2
done
実行例は以下の通りです。
$ sh test.sh a b c d e f
a
c
e
上記の実行例を見ると分かると思いますが、参照が2個づつスライドしています。このようにshiftコマンドにスライドさせたい数をしていることで指定した数だけ参照をずらすことが可能です。 もう1とつ忘れていけないのが「$0」は何を参照しているかということです。
#!/bin/sh

echo $0
実行例は以下の通りです。
$ sh test.sh
test.sh

$0は上記の通りスクリプト名を参照しています。

特殊変数

$-(ダラー・ハイフン)

シェル起動時のフラグを保持しています。
シェル起動時のフラグとはシェルオプションと言われるもので、$-は有効になっているシェルオプションを表現するフラグの文字列として表現したものです。
この変数の内容を出力していみると以下のように表示されます。このhimBHという文字列がシェル起動時のフラグです。

 $ echo $-
 himBH

ではシェルオプションにはどういったものがあるか見てみます。シェルオプションの一覧を表示するにはsetコマンドを使います。出力例は以下の通りです。
$ set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
igncr           off
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off

各シェルオプションとフラグの関係は下表の通りです。

シェルオプション フラグ 説明
allexport a 変数代入時に自動的にexportを実行する。
braceeexpand B プレース展開を有効にする。
emacs - emacs入力モードを有効にする。
errexit e コマンドが異常終了ステータスで終了するした場合にシェルを終了する。
errtrace E
functrace T
hashall h コマンドの位置を記憶し、検索時間を短縮する。
histexpand H !(exclamation point:エクスクラメーション・ポイント)によるヒストリの置換を有効にする。
igncr -
ignoreeof -
interactive-comments -
keyword k ?
monitor m ジョブコントロールを有効にする。
noclobber C すでに存在するファイルへのリダイレクトを禁止する。
noexec n
noglob f ワイルドカード(*、?)の展開を禁止する。
nolog -
notify b バックグラウンドジョブが終了した際の通知を有効にする。
nounset u 未設定パラメータへの参照をエラーにする。
onecmd t ?
physical P cd/cwdで-Pオプション(シンボリックによるパスではなく実際のパスを表示)を常に有効にする。
pipefail -
posix -
plivileged p 特権モードを有効にする。
verbose v コマンド入力時にエコー表示する。
vi - vi入力モードを有効にする。
xtrace x コマンド実行時に、展開後のコマンド行表示を有効にする。
対話モードの場合はiフラグが立ちます。以下のように対話モードであるか検出する例を見かけたりします。
[[ "$-" != *i* ]] && return

ブレース展開

{}(ブレース)で囲まれた短縮表現を展開することです。
呼んでもサッパリ分からないと思いますので、とりあえず以下の例を見てください。

 $ echo {a..z}
 a b c d e f g h i j k l m n o p q r s t u v w x y z
{}(ブレース)で囲まれた短縮表現の「a..z」が展開されて出力されているのが分かると思います。
また、固定の文字列と組み合わせてこんな使い方もできます。
 $ for v in test_{01..09}.log; do
 > echo ${v};
 > done
 test_01.log
 test_02.log
 test_03.log
 test_04.log
 test_05.log
 test_06.log
 test_07.log
 test_08.log
 test_09.log
可変部分を短縮表記でなくても動作します。
 $ for v in test_{a,b,c}.log; do
 > echo $v
 > done
 test_a.log
 test_b.log
 test_c.log
空文字的なものも含めることができます。
 $ for v in test{,.log}; do
 > echo ${v}
 > done
test
test.log
*(アスタリスク)も利用できます。アスタリスクは該当するファイル名に展開されるようです。
 $ echo {.vimrc,.*}
 .vimrc . .. .bash_history .bash_profile .bashrc .gem .gitconfig .inputrc .profile .screenrc .ssh .vim .viminfo .vimrc