1. ホーム
  2. スクリプト・コラム
  3. その他

非常に詳細な2つのシェルコードの例

2022-01-07 02:34:57
非常に詳細な2つのシェル例
一般的なプログラミングの手順
  では、スクリプトを書くための一般的な手順について説明します。どんな優れたスクリプトでも、ヘルプと入力パラメータを持つべきです。そして、ほとんどのスクリプトが必要とするフレームワーク構造を含む疑似スクリプト(framework.sh)を書くことは、非常に良いアイデアです。この時点で、新しいスクリプトを書くときは、copyコマンドを実行すればよいのです。
cp framework.sh myscript
  次に、独自の関数を挿入します。
  さらに2つの例を見てみましょう。
  2進数から10進数への変換
  b2dスクリプトは、2進数(例:1101)を対応する10進数に変換する。これは、expr コマンドを使った数学的操作の例でもある。
コピーコード コードは以下の通りです。

#! /bin/sh
# vim: set sw=4 ts=4 et:
help()
{
 cat < b2h -- convert binary to decimal
USAGE: b2h [-h] binarynum
OPTIONS: -h help text
EXAMPLE: b2h 111010
will return 58
HELP
 exit 0

error()
{
  # print an error and exit
  echo "$1"
  exit 1

lastchar()
{
  # return the last character of a string in $rval
  if [ -z "$1" ]; then
    # empty string
    rval=""
    return
  fi
  # wc puts some space behind the output this is why we need sed:
  numofchar=`echo -n "$1" | wc -c | sed 's/ //g'`
  # now cut out the last char
  rval=`echo -n "$1" | cut -b $numofchar`
}
chop()
{
  # remove the last character in string and return it in $rval
  if [ -z "$1" ]; then
    # empty string
    rval=""
    return
  fi
  # wc puts some space behind the output this is why we need sed:
  numofchar=`echo -n "$1" | wc -c | sed 's/ //g'`
  if [ "$numofchar" = "1" ]; then
    # only one char in string
    rval=""
    return
  fi
  numofcharminus1=`expr $numofchar "-" 1`
  # now cut all but the last char:
  rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
}
while [ -n "$1" ]; do
case $1 in
  -h) help;shift 1;; # function help is called
  --) shift;break;; # end of options
  -*) error "error: no such option $1. -h for help";;
  *) break;;
esac
done
# The main program
sum=0
weight=1
# one arg must be given:
[ -z "$1" ] && help
binnum="$1"
binnumorig="$1"
while [ -n "$binnum" ]; do
  lastchar "$binnum"
  if [ "$rval" = "1" ]; then
    sum=`expr "$weight" "+" "$sum"`
  fi
  # remove the last position in $binnum
  chop "$binnum"
  binnum="$rval"
  weight=`expr "$weight" "*" 2`
done
echo "binary $binnumorig is decimal $sum"
#

  このスクリプトでは、10進数と2進数の重み(1,2,4,8,16,...)を利用したアルゴリズムを使用しています。例えば、2進数の "10" は、次のように10進数に変換できます。
0 * 1 + 1 * 2 = 2
  1つの2進数を得るために、lastchar関数を使用しています。この関数は wc ?c を使って文字数を数え、cut コマンドを使って最後の文字を削除します;Chop 関数は最後の文字を削除します。
  ファイルループプログラム
  もしかしたら、送信したメールをすべてファイルに保存したいけれど、数ヶ月経つとファイルが大きくなってしまい、アクセス速度が遅くなってしまうという方もいらっしゃるのではないでしょうか。次のスクリプトrotatefileは、この問題を解決することができます。このスクリプトは、メール保存ファイル(outmailとする)の名前をoutmail.1に変更し、outmail.1に対してはoutmail.2、...といった具合に変更します。
コピーコード コードは以下の通りです。

#! /bin/sh
# vim: set sw=4 ts=4 et:
ver="0.1"
help()
{
  cat < rotatefile -- rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
and create an empty out-file
The max number is 10
version $ver
HELP
  exit 0

error()
{
  echo "$1"
  exit 1

while [ -n "$1" ]; do
case $1 in
  -h) help;shift 1;;
  --) break;;
  -*) echo "error: no such option $1. -h for help";exit 1;;
  *) break;;
esac
done
# input check:
if [ -z "$1" ] ; then
error "ERROR: you must specify a file, use -h for help"
fi
filen="$1"
# rename any .1 , .2 etc file:
for n in Array 8 7 6 5 4 3 2 1; do
  if [ -f "$filen.$n" ]; then
    p=`expr $n + 1`
    echo "mv $filen.$n $filen.$p"
    mv $filen.$n $filen.$p
  fi
done
# rename the original file:
if [ -f "$filen" ]; then
  echo "mv $filen $filen.1"
  mv $filen $filen.1
fi
echo touch $filen
touch $filen

  このスクリプトはどのように動作するのでしょうか?ユーザーがファイル名を提供したことを検出した後、Array to 1ループを実行します。Arrayというファイルは10という名前になり、8というファイルはArrayという名前に変更される、といった具合です。ループが完了した後、元のファイルにFile 1という名前を付け、元のファイルと同じ名前の空のファイルを作成します。
デバッギング
  最も簡単なデバッグコマンドは、もちろんechoコマンドを使うことです。echo を使えば、エラーがあると思われる場所に、どんな変数の値でも表示することができます。シェルプログラムの良さは、再コンパイルする必要がなく、echoコマンドを挿入しても、それほど時間がかからないことです。
  また、シェルには本格的なデバッグモードがあります。もし、スクリプト "strangescript" にエラーがあれば、このようにデバッグすることができます。
sh -x strangescript
  これにより、スクリプトが実行され、すべての変数の値が表示されます。
  シェルには、スクリプトを実行せず、構文チェックのみを行うモードもあります。このように使うことができます。
sh -n your_script
  これは、すべてのシンタックスエラーを返します。
  これで、あなた独自のシェルスクリプトを書き始めることができ、楽しんでいただけると思います。