By General System Manager Tamekichi.1998.3.20
<目次>
0. はじめに
1. Cシェル・スクリプトの書き方
1-1) Cシェル内での変数への値の設定・標準出力・ファイルへの書込み・実行方法
1-2) 分岐処理(if文)・ファイルの存在チェック・ディレクトリの存在チェック
1-3) 起動パラメータを持つCシェル・スクリプトを作る
1-4) UNIXコマンドの戻り値をCシェル変数へセットする
1-5) 反復処理(while, goto文)
1-6) Cシェルの便利な機能(ファイル名・パス名編集)
2. awk(オーク)言語
2-1) awk, nawk言語の書式
2-2) awk言語の処理(基本)
2-3) nawk, awk言語の処理(分岐処理・正規表現)
2-4) awk, nawkコマンドで2次Cシェルスクリプトを生成する
2-5) awk, nawkコマンドのCシェルスクリプトへの応用
2-6)フィルドセパレータがスペース以外のテキストファイルを編集する
2-7)awk, nawkの組込み関数を使用する。
・文字列の長さを取得する〜length関数)
・文字列の一部を抜出す〜substr関数)
2-8)変数内の文字列を置換する(sedコマンドの利用)
3. Cシェルスクリプトとawkコマンドの応用
・実用Cシェルスクリプト・サンプル
(Cシェル変数をawk内に取り込む方法等)
4. 正規表現について
4-1) sedコマンドでの使用例
4-2) 正規表現
4-3) 正規表現(文字クラス)
4-4) 正規表現の高度な使用例
5.講座を終了して、トップメニューに戻る
<はじめに>
Cシェルスクリプト(以下、略してCシェル)は、コンパイルの必要無いインタプリタ
言語です。UNIXマシン上ではほとんど互換があり、移植性も抜群です。
最近では、パソコン上での開発環境でも使用でき、動作できるような環境もあると聞きます。
UNIXマシンって何?って思われる方も多いかと思います。UNIXというのは、OS
のことでパソコンでいうと、MacOS や Windows95のことです。UNIXというOSは、
UNIXマシンと呼ばれるコンピュータ上で動作します。
UNIXマシンはPCと比べて高性能であると同時に信頼性や同時実行性に優れていて、
インターネット上の各サイトの主要コンピュータとして採用されています。
awk(オーク)言語は、あまり聞いた事がないと思いますが、これもコンパイルの必要無い
インタプリタ言語で、UNIXでもほぼ標準で使用できます。
awk言語は、テキスト編集には欠かせない言語です。便利な関数も用意されていて、とても
万能です。CシェルとUNIXコマンドを組み合わせて使用すると、驚くようなことがで
きます。
また、nawkコマンドというのがあり、awkコマンドの書式をそのままサポートしつつ、拡張
機能や、機能の強化が計られています。ですから、実際に使用する際は、nawkコマンドがあ
れば、nawkコマンドの方を使用してください。SUNのSolaris2.Xでは、標準で使えるようです。
Cシェルもawkも、Perl言語のようにインストールしなくてもすぐに使えます。
「Cシェルで処理全体の流れを制御して、テキスト編集処理の部分に(Cシェルの中で)
awkをコールしてテキスト編集処理を担当させる。」という作り方が一般的です。
近年は、UNIXマシンの性能も良くなり、Cシェルやawk, nawkのようなインタプリタ言語
でも充分な性能がだせるので実用的でもあります。
UNIXシステム管理者は、Cシェルやawk等を絶対に覚えるべきです!
1. Cシェル・スクリプトの書き方
UNIXマシン上で、viコマンド等のテキストエディタを用いてCシェルスクリプトを書きます。
ファイルを生成したりするCシェルスクリプトを記述する時は、ファイル権限やディレクトリ
権限などに注意すること。UNIX上でのプログラム不具合の2割が権限の問題等です。
「初級・中級者向け」
1-1)Cシェル内での変数への値の設定・標準出力・ファイルへの書込み・実行方法
(標準出力とは、Cシェルスクリプト実行時に画面上に出力するということ)
% vi test1-1.shl (return)
-----------------------------------------------------------------------------------
#!/bin/csh ← 1行目には固定で記述。
set HENSUU1 = "ため吉" ← setコマンドは、変数に文字列を代入する。
変数名は文字であれば何でもよい。
set FILE1 = "/tmp/file.txt" ← setコマンドは、変数に文字列を代入する。
変数名は文字であれば何でもよい。
@ NUMBER1 = 10 ← @ マークを使用すると、変数に数値を代入できます。
@ NUMBER2 = $NUMBER1 + 10 ← 数値の足し算
変数を使用するときは、変数名の頭に"$"マークを付加
@ NUMBER3 = $NUMBER2 - $NUMBER1 ← 数値の引き算
@ NUMBER4 = $NUMBER2 * $NUMBER1 ← 掛け算
@ NUMBER5 = $NUMBER2 / $NUMBER1 ← 割り算
@ NUMBER6 = $NUMBER2 % $NUMBER1 ← 割り算した余りの算出
# --------------
# 計算結果の表示
# --------------
echo -n "NUMBER1 = " $NUMBER1 ←変数を使用するときは、変数名の頭に"$"マーク
echo " " を付ける。
echo -n "NUMBER2 = " $NUMBER2
echo " "
echo -n "NUMBER3 = " $NUMBER3
echo " "
echo -n "NUMBER4 = " $NUMBER4
echo " "
echo -n "NUMBER5 = " $NUMBER5
echo " "
echo -n "NUMBER6 = " $NUMBER6
echo " "
echo "---------------------------" ←echoコマンドは、標準出力
echo -n "私は" $HENSUU1 "です。" ←"-n"オプションで 文字列を羅列して標準出力。
また、setコマンド等で設定した変数を使用する
時は、変数名の頭に"$"マークを付けること。
echo " " ←1つ前の行で、echoコマンドの"-n"オプションを
使用した後は、故意に空文字を表示させる。
echo "---------------------------"
echo "---------------------------" > $FILE1 ←リダイレクション">"でファイルへ
上書き出力または、新規出力。
echo -n "私は" $HENSUU1 "です。" >> $FILE1 ←">>"でファイルへ追加出力
echo " " >> $FILE1
echo "---------------------------" >> $FILE1
exit ← シェルスクリプト終了
-----------------------------------------------------------------------------------
% chmod 755 ./test.shl (return) ← Cシェルスクリプトを作成したら、必ず実行権限
を付与します。
% ./test.shl (return) ← 実行!
1-2)分岐処理(if文)・ファイルの存在チェック・ディレクトリの存在チェック
<書式>
------------------------------------------------------------------
if文 if (条件1) then ← 条件1が真のとき、処理1が実行される。
処理1
else if (条件2)then ← 条件2が真のとき、処理2が実行される。
処理2
else ← 条件1にも条件2にも当てはまらなかった場合、
処理3 処理3を実行する。
endif
------------------------------------------------------------------
% vi test1-2.shl (return)
-----------------------------------------------------------------------------------
#!/bin/csh
set BASEDIR = "/export/home" ← ディレクトリ名を代入
set FILENAME1 = "file1.txt" ← ファイル名を代入
set FILENAME2 = "file2.txt" ← ファイル名を代入
set FILE1 = $BASEDIR/$FILENAME1 ←ディレクトリ名を追加したファイル名を代入
set FILE2 = $BASEDIR/$FILENAME2 ←ディレクトリ名を追加したファイル名を代入
(なるべくファイル名は、フルパスで記述するように
心がける。フルパスで記述しておかないと、実行の
仕方によって、思いがけないところへファイルを生
成してしまったりするので注意すること。)
# ------------------------
# FILE1の存在チェック ← "#"は、コメントになる。
# ------------------------
if (-e $FILE1) then ← if文の"-e"は、ファイル存在時に真となる
echo -n $FILE1 "は、存在します。"
echo " "
else
echo -n $FILE1 "は、存在しません。"
echo " "
endif
# ------------------------
# FILE2の存在チェック
# ------------------------
if !(-e $FILE2) then ← "!"を付けると逆の意味が真になる。
echo -n $FILE2 "は、存在しません。"
echo " "
else
echo -n $FILE2 "は、存在します。"
echo " "
endif
# ------------------------
# BASEDIR の存在チェック ← "#"は、コメントになる。
# ------------------------
if (-e $BASEDIR) then ← "-e"は、ディレクトリでも存在すれば真
echo -n $BASEDIR "は、存在します。"
echo " "
else
echo -n $BASEDIR "は、存在しません。"
echo " "
endif
# -----------------------------
# ファイルか、ディレクトリか?
# -----------------------------
if (-f $BASEDIR) then ← "-f"は、ファイルなら真。ディレクトリでは偽。
echo -n $BASEDIR "は、ファイルです。"
echo " "
else
echo -n $BASEDIR "は、ファイルではありません。"
echo " "
endif
# -----------------------------
# ファイルか、ディレクトリか?
# -----------------------------
if (-d $BASEDIR) then ← "-d"は、ディレクトリなら真。ファイルなら偽。
echo -n $BASEDIR "は、ディレクトリです。"
echo " "
else
echo -n $BASEDIR "は、ディレクトリではありません。"
echo " "
endif
# --------------------------------------------
# もちろん、このような if文の使い方もできます。
# 下の例は、処理的には、あんまり意味がありませんが、
# if文の使い方を見てください。(文字列)
# ---------------------------------------------
set HENSUU1 = "TAME1" ←変数に文字列を代入
set HENSUU2 = "TAME1"
set HENSUU3 = "TAME2"
set HENSUU4 = "TAME3"
if ($HENSUU1 == $HENSUU2) then ← 等価条件式
echo -n $HENNSUU1 "と" $HENSUU2 "は、同じです。" (この例の場合は、これが真)
else if ($HENSUU1 != $HENSUU) then ← 不等価条件
echo -n $HENSUU1 "と" $HENSUU2 "は、異なります。"
endif
if ( ($HENSUU1 == $HENSUU2) && ($HENSUU3 == $HENSUU4) ) then ←論理積条件
echo -n $HENSUU1 "と" $HENSUU2 "は同じであり、かつ"
echo " "
echo -n $HENSUU3 "と" $HENSUU4 "は同じです"
echo " "
else if ( ($HENSUU1 == $HENSUU2) || ($HENSUU3 == $HENSUU4) ) then ←論理和条件
echo -n $HENSUU1 "と" $HENSUU2 "は同じであるか、または" (この例の場合は、
echo " " この条件が真)
echo -n $HENSUU3 "と" $HENSUU4 "は同じです"
echo " "
endif
# --------------------------------------------
# 下記のような数値に対する if文の使い方
# ---------------------------------------------
@ NUMBER1 = 1 ←変数に数値を代入
@ NUMBER2 = 2
@ NUMBER3 = 3
@ NUMBER4 = 4
if ( ($NUMBER1 == $NUMBER2) || ($NUMBER3 <= $TAME4) ) then
echo -n $NUMBER1 "と" $NUMBER2 "は同じであるか、または"
echo " "
echo -n $NUMBER3 "は" $NUMBER4 "以下である。"
echo " "
else if ( ($NUMBER1 < $NUMBER2) && ($NUMBER3 >= $TAME4) ) then
echo -n $NUMBER1 "は" $NUMBER2 "より小さく、かつ、"
echo " "
echo -n $NUMBER3 "は" $NUMBER4 "以上である。"
echo " "
endif
exit
-----------------------------------------------------------------------------------
1-3)起動パラメータを持つCシェル・スクリプトを作る
% vi test1-3.shl
-----------------------------------------------------------------------------------
#!/bin/csh
if ($#argv != 2 ) then ← $#argvは、Cシェル実行時に渡された
起動パラメータの個数が格納されている。
echo
echo "起動パラメータがヌルです"
echo " "
echo "(例)."
echo " test1-3.shl <パラメータ1> <パラメータ2>"
echo " "
exit ←Cシェル・スクリプトの終了
endif
set DIRNAME = $argv[1] ←起動パラメータ1を $DIRNAME変数に代入
set FILENAME = $argv[2] ←起動パラメータ2を $FILENAME変数に代入
if !(-e $DIRNAME/$FILENAME) then
echo -n $DIRNAME/$FILENAME "というファイルは存在しません"
echo " "
endif
exit
-----------------------------------------------------------------------------------
<実行例>
% test1-3.shl /export/home test1.txt
<備考>
・Cシェルスクリプト実行時に、起動パラメータ無しで実行された時に、$argv[1]など
を無理に使おうとすると実行エラーになりますので、必ず$#argvを見て、実行時に起
動パラメータが何個指定されたかをチェックするようにしてください。
・$argv[*]を使用すると、指定された起動パラメータ(自分のCシェルスクリプトファ
イル名を含む)の文字列が返されます。
「中級・上級者向け」
1-4)UNIXコマンドの戻り値を変数へセットする
(1つの変数に複数行の値をセットした場合の、配列の使い方)
<このような環境を例にして>
% cd /export/home ← /export/homeディレクトリに移る。
% ls ← lsコマンド発行
test1.txt ← 4つのファイルがあることを確認。
test2.txt
test3.txt
test4.txt
%
% vi test1-4.shl (return)
-----------------------------------------------------------------------------------
#!/bin/csh
set BASEDIR = "/export/home" ←ディレクトリ名を変数にセット
cd $BASEDIR ←CD(Change Directory)コマンドでカレントディレク
トリを$BASEDIRに移す。
set PWDINF = `pwd` ←"`"文字で、UNIXコマンドを囲むことにより、その
コマンドを実行したことになる。ここでは、pwdコマ
ンド(カレントディレクトリの表示)を実行した結果
である「/export/home」と文字列が、$PWDINF変数に
格納される。
echo $PWDINF ←カレントディレクトリを標準出力。
set LSLIST = `ls` ← "`"文字で、UNIXコマンドを囲むことにより、その
コマンドを実行したことになる。
よって、ここでは、lsコマンドを発行した結果(
標準出力)が、$LSLIST変数に格納されることになる
$BASEDIRディレクトリ以下に複数のファイルがあ
った場合、lsコマンド発行の結果では複数のファ
イル名が $LSLIST変数の中に格納されることになる。
この例の場合は、先にも説明したように、$BASEDIR
ディレクトリ下に
test1.txt
test2.txt
test3.txt
test4.txt
の4つのファイルがあるという設定なので、$LSLIST
変数には4つのファイル名が格納されます。
echo $LSLIST[1] ← 格納されている4つのファイル名を表示させるには、
echo $LSLIST[2] $LSLIST[n]という記述を行います。
echo $LSLIST[3] 配列1〜4まで、lsコマンドを発行した時に標準出力
echo $LSLIST[4] される順に格納されます。
echo $#LSLIST ← $#LSLISTは、配列LSLISTの配列数を返す。この場合は、
配列数4なので、4と表示される。
shift LSLIST ← shiftコマンドは、指定した配列に格納されている内
容をシフトします。
<shift LSLISTを実行したら>
$LSLIST[1]に格納されていたデータは失われます。
$LSLIST[2]に格納されていたデータは、$LSLIST[1]へ
$LSLIST[3]に格納されていたデータは、$LSLIST[2]へ
$LSLIST[4]に格納されていたデータは、$LSLIST[3]へ
$LSLIST[4]には、値がありません。というか、
$LSLIST[4]という配列自体が無くなります。
要するに、shiftコマンドを1回実行する毎に、配列
数を1つづつ減らしながら、上にシフトされる。
echo $LSLIST[1] ← shift LSLISTを実行した後には、$LSLIST[4]という
echo $LSLIST[2] 配列が無くなるので、"echo $LSLIST[4]" を実行しよ
echo $LSLIST[3] うとすると、エラーになってしまい、Cシェルは強制
#echo $LSLIST[4] 終了されてしまいます。
気を付けてください。
echo $#LSLIST ← $#LSLISTは、配列LSLISTの配列数を返す。
shiftコマンドが1回発行された後なので、$#LSLIST
は、3を返す。
-----------------------------------------------------------------------------------
1-5)反復処理(while, goto文)
反復処理と配列変数を使うことにより、巧みな連続操作が可能となる。
ここでは、goto文、while文の説明をしているが、その他にも foreach文等がある。
<書式>
------------------------------------------------------------------
while文 while (条件) ← 条件が真のとき、処理が実行される。
:
処理
:
end
------------------------------------------------------------------
goto文 goto