ソフトウェア工学 A
NAGASAKA Yasunori
2009/09/29
|
http://edu.isc.chubu.ac.jp/naga/index.html で公開中
Table of Contents
1 はじめに (第 1 週)
1.1 凡例
1.2 目標
1.3 進め方
1.4 建設的な横着とは
1.5 練習問題
2 基本的な使い方 (第 1 週)
2.1 Linux の起動と終了
2.2 GNOME, X Window System の使い方
2.3 端末(ターミナル)エミュレータの使い方
2.4 Web ブラウザ firefox の使い方
2.5 出席確認用ファイルの作成方法
3 エディタ (第 1, 2 週)
3.1 gedit
3.2 vi (p.161)
3.2.1 vi の代表的なコマンド
3.2.2 vi の操作の実際
3.3 emacs (p.152)
3.3.1 emacs の代表的なコマンド
3.3.2 emacs の操作の実際
3.4 日本語入力 (p.170)
3.5 練習問題
4 UNIX, Linux の特徴 (第 2, 3 週)
4.1 UNIX, Windows の特徴と相違点 (p.22)
4.2 Login, Logout (p.36)
4.3 一般ユーザと特権(管理者)ユーザ (p.38)
4.4 パスワード (p.36,59)
4.5 シェル, Shell (p.64,115)
4.6 コマンド (p.45,66)
4.7 man, オンラインマニュアル (p.40,82)
4.8 練習問題
5 データを記録、参照する仕組 (第 4, 5 週)
5.1 ファイルとディレクトリ (p.72,87)
5.2 パス : ファイルの位置 (p.56,87)
5.3 ファイルの属性、アクセス制限 (p.92)
5.3.1 アクセス権、アクセス制限の詳細
5.4 練習問題
6 コマンド (第 6, 7 週)
6.1 凡例
6.2 UNIX の代表的なコマンド
6.2.1 ディレクトリ操作 (p.103)
6.2.2 ファイル操作 (p.91,96)
6.2.3 テキストファイル操作 (p.96,103)
6.2.4 ユーティリティ (p.177)
6.2.5 プロセス制御 (p.192)
6.3 練習問題
7 シェルによる操作環境 (p.115) (第 8, 9 週)
7.1 コマンドラインの編集、文字列補完 (p.144)
7.2 ファイル名の置換、字句解析 (p.143)
7.3 エイリアス (p.145)
7.4 ヒストリ (p.141)
7.5 シェル変数 (p.139)
7.6 環境変数 (p.136)
7.7 設定ファイル .cshrc, .login (p.147)
7.8 標準入出力、リダイレクト、パイプ (p.118,122)
7.9 ジョブコントロール (p.125)
7.10 練習問題
8 パターン処理言語 awk (第 10, 11 週)
8.1 awk の概要、実行方法
8.2 awk のプログラム : 変数
8.3 awk のプログラム : パターンの記述
8.4 正規表現
8.5 awk のプログラム : アクションの記述
8.6 サンプルプログラム
8.7 練習問題
9 シェルスクリプト、作業の自動化 (第 12, 13 週)
9.1 シェルスクリプトとは
9.2 変数、パラメータ
9.3 コマンド置換
9.4 引用、クォート
9.5 制御構造
9.5.1 if
9.5.2 for
9.5.3 while
9.5.4 break
9.5.5 continue
9.6 ファイル名の操作
9.7 シェルスクリプトの例
9.7.1 大文字の拡張子 JPG を小文字の jpg に変更する
9.7.2 一定の形式のファイル名で通し番号を付けてファイルを作成する
9.7.3 デジタルカメラの画像ファイルの名前を内容がわかるファイル名に変更する
9.7.4 ls の結果を日時をファイル名にしたファイルに記録する
9.7.5 複数のファイルで特定の単語を含む行数の一覧表を作成する
9.7.6 学生の出席日数を数える
9.8 練習問題
10 OS が備える主要な機能
10.1 カーネル
10.2 プロセス、スケジューリング
10.3 メモリ管理、仮想記憶
10.4 ファイルシステム
10.5 システムコール
10.6 ユーザインタフェース
10.7 入出力、割り込み
10.8 通信、ネットワーク
10.9 練習問題
11 基本的な使い方 (旧システム用)
11.1 X Window System の使い方
11.2 kterm の使い方
11.3 Web ブラウザ firefox, mozilla の使い方
11.4 出席確認用ファイルの作成方法
1 はじめに (第 1 週)
1.1 凡例
この後の文中ではコンピュータで実際に実行するコマンド、命令文の記述が数多く現れる。
そのようなコマンドについては、
% ls -la
のように記述される。この場合、端末エミュレータのコマンドプロンプト
("a01%" のようにコンピュータ名と % の組み合わせで表される)
に続けて ls -la を入力して Enter (Ret も可) キーを入力することで実行される。
文中左端の % はコマンド入力であることを表しているので、
自分で入力する必要はない。
各章のタイトルには参考書の関連した記述のページを付記してあるので、
併せて読んで参考にするとよい。
参考書 : 「UNIX本格マスター 基礎編」, 後藤大地, 小澤正紀, (技術評論社)
1.2 目標
- UNIX, Linux の基本を理解して使えるようになる。
- 大量のデータに対して、
様々な処理を組み合わせないとできない複雑な処理を行ないたい場合に、
コンピュータでいかに効率良く実行できるようにするか、
その方法、考え方を身に付ける。
- OS の役割、処理の基本、関連する概念を理解する。
1.3 進め方
- 講義も順次進めるが、説明だけの時間はなるべく少なくして、
実際に UNIX, Linux で実行、確認できる具体的な練習問題を多くする。
経験を通して理解する。
- 質問、問いかけの形で対話を多くする、また問題を通して考える時間を多くする。
結果として能動的に参加する時間を増やす。
- 抽象的な概念の理解だけではなく、UNIX, Linux の具体的な使い方を身に付ける。
様々なコマンドを使いこなせるようになり、
今後の卒研などで活用できることを目指す。
1.4 建設的な横着とは
コンピュータを「建設的な横着」をするための機械ととらえる。
一定の手順、単純な作業を多数回繰り返す場合に、人が手でやるのではなくて
コンピュータに必要な指示を与えてかわりにやらせること、作業を自動化すること。
同じ時間をかけるなら、人間の能力は単純作業の繰り返しに使うのではなく、
その作業をコンピュータにやらせるにはどうしたらよいか「考える」ところに使うべき。
建設的な横着ができるようになるための、方法、考え方を身に付けることを目指す。
1.5 練習問題
- あなたの知っている OS を挙げてみなさい。
- 普段パーソナルコンピュータ、Windows をどんなことに使っているか考えなさい。
- OS の機能にはどんなものがあるか考えなさい。 (情報処理工学で既出)
- デジタルカメラで撮影した画像ファイルが 10 個ある。
内容がわかるファイル名に変更したい場合、自分ならどう実行するか考えなさい。
- デジタルカメラで撮影した画像ファイルが 100 個ある。
内容がわかるファイル名に変更したい場合、自分ならどう実行するか考えなさい。
- デジタルカメラで撮影した画像ファイルが 1000 個ある。
内容がわかるファイル名に変更したい場合、自分ならどう実行するか考えなさい。
デジタルカメラの画像ファイルの名前の例
DCN00001.jpg → ryokou0001.jpg
DCN00002.jpg → ryokou0002.jpg
DCN00003.jpg → ryokou0003.jpg
DCN00004.jpg → ryokou0004.jpg
DCN00005.jpg → ryokou0005.jpg
・
・
・
DCN00999.jpg → ryokou0999.jpg
DCN01000.jpg → ryokou1000.jpg
2 基本的な使い方 (第 1 週)
- 電源の入切、Login, Logout の手順を覚える。
- ユーザ名、パスワードを入力して、コンピュータに login できることを確認する。
- GNOME, X Window System の基本的な使い方を理解する。
- 端末(ターミナル)エミュレータの基本的な使い方を理解する。
- Web ブラウザ Firefox の基本的な使い方を理解する。
2.1 Linux の起動と終了
- 本体の電源スイッチを ON にすると、Windows と Linux を選択するメニューが表示されるので、
Linux を選択して Enter キーを入力する。何も選択しないで 30 秒間放置すると自動的に
Windows が選択されるので注意する。
- Login の画面になったらユーザ名とパスワードを入力する。
- Linux を終了して電源を切りたい場合は、デスクトップ画面上端のメニューから
システム → 終了を選ぶ。シャットダウンの処理の後自動的に電源が切れる。
2.2 GNOME, X Window System の使い方
X Window System は UNIX, Linux で標準的に使用されるビットマップディスプレイ、マウス、
Window 等を使用する GUI の実装である。
GNOME は X Window System 上で動作する統合デスクトップ環境である。

GNOME の画面
- デスクトップ画面の上端と下端にはそれぞれバーが表示される。
上端のバーは GNOME 全体のメニューでプログラムの起動や GNOME の終了などを指定できる。
下端のバーはタスク管理用で起動しているプログラムの名前でアイコンが表示され、
プログラムの切替や、仮想デスクトップの切替えなどができる。
- Window を移動させたい時は、
タイトルバーの真中付近でマウスの左ボタンを押したままにして移動させる。
- Window の大きさを変えたい場合は、
Window 外周の 4 辺上でマウスの左ボタンを押すとアイコンが矢印に変わるので、
その状態で変更する。
- 下になっている Window を前面に出したい場合はタイトルバー、
または Window 内部を左クリックする。
- Window を一時的にアイコンにして閉じておきたい時は、
タイトルバー右端にある 3 個のボタンの中で、"_"のボタンを押す。
すると Window が閉じて画面下部のバーに収納される。
アイコンをもとの Window に戻す時はバーの中のアイコンをクリックする。
- タイトルバー右端にある 3 個のボタンの中で、"□”は Window の最大化、
"X"は Window を閉じる機能が割り当てられている。
- マウスを使って文字列のコピー、貼り付けが行なえる。
コピーしたい文字列の端でマウスの左ボタンを押したまま移動させると、
領域が反転してバッファに記憶される。貼り付けはマウスの中ボタンを押すことで、
アクティブな Window のコマンドプロンプトまたは文字入力が可能な位置に貼り付けられる。
Windows と同じように編集メニューの「切り取り」,「コピー」,「貼り付け」
でもできる。
2.3 端末(ターミナル)エミュレータの使い方

端末エミュレータの画面
- 端末エミュレータを新たに起動したい時は、
デスクトップ上端のメニューから、
アプリケーション → システムツール → 端末 を選択する。
- 端末エミュレータを終了したい時はコマンドプロンプトから、
% exit
を入力して Enter キーを押す。またはファイルメニューから終了を選んでもよい。
- 端末エミュレータから起動して実行中のプログラムを終了させたい場合は
Ctrl - c を入力する。
Ctrl - z は中断するだけで終了しないので使わない。
- キー入力を何も受け付けなくなったら、
Ctrl - c や Ctrl - q を入力してみると直ることがある。
2.4 Web ブラウザ firefox の使い方

firefox の画面
- firefox の起動はデスクトップ上端のメニューから、
アプリケーション → インターネット → Firefox を選択する。
- firefox の終了はファイルメニューの下端にある終了を選択する。
2.5 出席確認用ファイルの作成方法
2009 年度から教務課が運用するカードリーダーの出席登録状況で確認するので、
下記の出席確認ファイルを作成する必要はなくなった。
- 以下の説明で ???? は年度を表す 4 桁の数字 (2006, 2007, 2008, ...) とする。
実習の時間になって Linux を起動したら、
毎回端末エミュレータのコマンドプロンプトから、
% touch /usr7/denshi2/naga/????/その日の日付4桁/学籍番号
を実行しておく。
例として、10 月 3 日の講義に ed05000 の学生が出席した場合は、
% touch /usr7/denshi2/naga/????/1003/ed05000
となる。正しく登録できたかどうかは、
% ls /usr7/denshi2/naga/????/その日の日付4桁
または、
% ls -l /usr7/denshi2/naga/????/その日の日付4桁
を実行して、自分の番号があるか見るとわかる。
各回の遅刻と欠席の確認はこのファイルの記録日時で集計するが、
別の日や時間に実行すると無効になるので注意する。
3 エディタ (第 1, 2 週)
GNOME の環境で使用する代表的なエディタとして gedit がある。
GUI を考慮して開発されており、多くの編集コマンドがメニュー形式で利用できる。
Windows 環境のアプリケーションに似たコマンド体系になっているので、
Windows に慣れている人は理解し易い。
UNIX で使用するその他の代表的なエディタとして vi, emacs がある。
どちらも非常に高機能なエディタで、
キーボードからのコマンドの入力ですべての編集機能が利用でき、
一旦コマンドを覚えるとほとんどの操作をキーボードから行なえるので、
早く効率良く文書作成ができる。その反面、GUI, メニューなどはないので、
慣れるまでは使いこなすのが難しいと感じるかもしれない。
すべてのエディタの使い方に精通する必要はないので、どれか一つ、
自分が使い易いと感じたものの使い方を覚えればよい。
また、すべてのコマンドを覚える必要はないが、
効率良く作業を進めるにはカーソルキーの移動と文字の削除だけでは不足するので、
指定した範囲をまとめて削除、コピーする方法程度は覚える必要がある。
3.1 gedit

gedit の画面の例
gedit は多くの編集コマンドがメニューおよびボタンの形式で利用できるので、
Windows のメモ帳やワードパッド、Word などのプログラムを使用した経験があれば、
マニュアル等を読まなくても容易に使え、初心者でも使い易い。
メニューの項目は Windows のアプリケーションのメモ帳に類似しており、日常的に
Windows を使用する人は馴染み易いと思われる。
文書作成時にはファイルメニュー、編集メニュー内の機能を利用することが多い。
以下にそれぞれのメニューに含まれる機能の一覧を示す。

gedit のメニュー(1)

gedit のメニュー(2)
3.2 vi (p.161)
vi は、コマンドモードと挿入(インサート)モードという二つのモードを
必要に応じて切替えながら編集を行なう、
モードを強く意識したエディタである。
コマンドモードでは、編集したい位置に移動したり、
いろいろな編集機能を指定するコマンド(命令)が実行できる。
挿入モードでは、文字を入力する。
特徴として、同じ文字がその時のモードにより異なる意味を持つ。
例として、文字'h'はコマンドモードではカーソルの左への移動として解釈され、
挿入モードでは入力文字としてカーソル位置に挿入される。
Windows, Unix どちらの環境でも、
vi のように操作状態を 2 種類のモードで明確に区別しているエディタは数少ないので、
はじめて使用する場合は多少戸惑うかもしれない。

vi におけるモードの遷移
挿入モードとコマンドモード間の切替えは、
コマンドモードから挿入モードへは、以下の挿入コマンドのどれかによって、
また挿入モードからコマンドモードへは ESC キーを入力することで切り替える。
ヤンクとは,カットバッファに記憶することを表す。
ペーストとは,カットバッファの内容を挿入することを表す。
挿入モードでは、基本的に文字の入力しかできないが、
オリジナルの vi から機能拡張された新しい vi の実装(vim, この講義でも使用している)では、
文字入力に加えて、上下左右のカーソルキーによるカーソルの移動、
BS および DEL キーによる文字の削除が可能になっている。
起動の仕方は、
% vi filename
のように、起動時に編集対象のファイルを同時に指定するか、または、
% vi
として起動しておいて、
以下の ex コマンドのファイル挿入コマンドで必要なファイルを指定して読み込む。
操作を間違えた時、表示がおかしくなった時は、ESC キーを入力すると直る場合がある。
3.2.1 vi の代表的なコマンド
以下に示すコマンドはすべてコマンドモードで実行する
○ exコマンド
:w : 現在のファイルに書き込む
:w filename : 指定したファイルに書き込む
:q : エディタの終了
:q! : エディタの強制終了(記録していない編集内容は破棄される)
:r : 現在のファイルを挿入
:r filename : 指定したファイルを挿入
:help : ヘルプを表示
(※ :wq : ファイルに書き込んでから終了、のように組み合わせての指定が可能)
○ 中止
ESC : コマンドの実行を中止する
○ 挿入コマンド
i : カーソルの前に挿入
I : 行の先頭文字の前に挿入
a : カーソルの後に挿入
A : 行末に挿入
o : 次行に挿入
O : 前行に挿入
○ 移動コマンド
h : カーソルを一文字左に移動
j : カーソルを一行下に移動
k : カーソルを一行上に移動
l : カーソルを一文字右に移動
^ : 行頭文字に移動
0 : 行頭に移動
$ : 行末に移動
[数字]G : [数字]行に移動
G : 最終行に移動
Ctrl+F : 次画面に移動
Ctrl+B : 前画面に移動
/[文字列] : [文字列]を検索 (n で次候補, N で前候補)
○ 編集コマンド
x : 文字の削除 (DEL, Delete)
X : 文字の削除 (BS, BackSpace)
d[移動コマンド] : 移動範囲を削除
dd : 行の削除
y[移動コマンド] : 移動範囲をヤンク
yy : 行のヤンク
p : カーソルの後(次行)にペースト
P : カーソルの前(前行)にペースト
上記に示したコマンドは多くのコマンドの中の一部に過ぎないが、
より詳しく vi の機能を知りたい場合は、チュートリアルプログラムを利用するとよい。
起動の仕方は、
% vimtutor
とする。その後は画面の指示にしたがって実際に操作しながら練習ができる。
3.2.2 vi の操作の実際
以下では vi を使用して文書を入力する時の典型的な操作の例を示す。
通常は編集対象のファイル(仮に sample.txt)を指定して起動する。
% vi sample.txt
カーソルの移動などが必要ならここで行なっておく。
現在はコマンドモードになっているので挿入モードに変更する。
次の行頭の(コマンド)はコマンドモードからの入力を表す。
(コマンド) i
挿入モードになると画面下端に次のように表示されるのでわかる。
-- 挿入 --
この状態で文字入力が可能となる。必要な文字を入力していき、編集コマンドを実行する時は、
適宜コマンドモードに変更して編集する。
一通り入力が終ったらファイルを記録して終了する。
(コマンド) :wq
ファイルに記録した後 vi が終了して端末エミュレータに戻る。
3.3 emacs (p.152)
emacs は編集時に特別なモードはなく、
入力したテキストはカーソルの位置にそのまま配置される。
また、カーソルの移動やいろいろなコマンドは、Ctrl や Meta キー
と文字キーを同時に押して指定する。
キーボードによっては Meta キー が使えない/存在しない時がある。
その場合は、ESC キー を押して「から」文字キーを押すことにより代用する。
以下が代表的なコマンドの入力方法である。
Ctrl-文字: Ctrl キー と文字キーを同時に押す
C-文字: 上記と同じ内容を表す
M-文字: Meta キー と文字キーを同時に押す、
または ESC キー を押して「から」文字キーを押す
リージョンとは、文書中の一まとまりの領域で、
マークの位置からカーソルのある位置の前までがリージョンの範囲となる。
操作を間違えた時、表示がおかしくなった時は、コマンドの中止 C-g を入力すると直る場合がある。
3.3.1 emacs の代表的なコマンド
○ 終了
C-x C-c : エディタの終了
○ コマンドの中止
C-g : 現在実行中のコマンドの中止
○ ファイルの読み込み/書き込み
C-x C-s : ファイルの保存
C-x C-w : 他のファイル名で保存
C-x C-f : ファイルを読み込む
C-x i : ファイルを挿入
○ ヘルプ
C-h t : 英語チュートリアルの表示
C-h T : 日本語チュートリアルの表示
C-h C-h : ヘルプ機能の一覧を表示
○ カーソルの移動
C-f : カーソルを一文字右に移動
C-b : カーソルを一文字左に移動
C-n : カーソルを一行下に移動
C-p : カーソルを一行上に移動
C-a : 行の先頭に移動
C-e : 行末に移動
C-v : 一画面下にスクロール
M-v : 一画面上にスクロール
M-< : 編集ファイルの先頭へ移動
M-> : 編集ファイルの末尾へ移動
C-s 文字列 : 文字列の検索
C-s で次候補
C-r で前候補
○ テキストの削除/移動/コピー
C-d : 一文字削除
C-k : 一行削除
DEL, BS : カーソルの前の文字を削除
C-Space : カーソル位置にマークを設定
M-h : カーソルのある段落をリージョンに指定する
C-x h : バッファ全体をリージョンに指定する
C-u C-Space : マークをつけた位置にカーソルを移動
C-x C-x : マークとカーソルの位置を入れ換える
C-w : リージョンを削除してカットバッファに記憶
M-w : リージョンを削除しないでカットバッファに記憶
C-k : カーソル位置より行末までを削除してカットバッファに記憶
M-k : 段落の終りまでを削除してカットバッファに記憶
C-y : カットバッファの内容をカーソル位置に挿入
○ ウィンドウの操作
C-x 2 : ウィンドウを上下に分割
C-x 5 : ウィンドウを左右に分割
C-x b : 編集ファイルの変更
C-x k : 編集ファイルから外す
C-x C-b : 編集ファイルの一覧を表示
C-x o : 他のウィンドウにカーソルを移す
C-x 0 : カーソルのあるウィンドウを消す
C-x 1 : カーソルのあるウィンドウだけにする
3.3.2 emacs の操作の実際
以下では emacs を使用して文書を入力する時の典型的な操作の例を示す。
通常は編集対象のファイル(仮に sample.txt)を指定して起動する。
% emacs sample.txt
emacs はモードレスなので起動直後から文字入力とコマンド入力が随時可能である。
必要な文字を入力していき、必要に応じて編集コマンドを実行する。
一通り入力が終ったらファイルを記録して終了する。
Ctrl-x Ctrl-s でファイルに記録、
Ctrl-x Ctrl-c で emacs が終了して端末エミュレータに戻る。
3.4 日本語入力 (p.170)
入力メソッドとして SCIM, 漢字変換システムとして Anthy という
二つのプログラムを組み合わせた日本語入力システムを使用する。
日本語に変換する時に使用するコマンドと、
コマンド表記の入力方法を以下に示す。
Ctrl-文字: Ctrl キー と文字キーを同時に押す
Shift-文字: Shift キー と文字キーを同時に押す
SCIM の代表的なコマンド
Ctrl-Space : 日本語入力の開始、停止
Space : 変換、次の候補
↑↓ : 変換候補の選択
← → : 文節の移動
Shift- ← : 文節の縮小
Shift- → : 文節の拡大
3.5 練習問題
- gedit で適当な文章を入力した後で、
gedit のコマンドを一通り実行して機能を確認しなさい。
- 数字とアルファベット 26 文字を並べた行 "0123456789abcdefg...xyz" を入力しなさい。
- gedit の選択範囲をコピーする機能を使って、上記の行を 100 行コピーしなさい。
それを ログインネーム-gedit.txt (例 ed04000-gedit.txt)として記録しなさい。
- 日本語入力の機能を使って、上記のファイルに自分の住所、学籍番号、
名前を記述しなさい。
- vi で適当な文章を入力した後で、vi の挿入コマンド、移動コマンド、
編集コマンドを一通り実行して機能を確認しなさい。
- アルファベット 26 文字と数字を並べた行 "abcdefg...xyz0123456789" を入力しなさい。
- vi のリージョンをコピーする機能を使って、上記の行を 100 行コピーしなさい。
それを ログインネーム-vi.txt (例 ed04000-vi.txt)として記録しなさい。
- 日本語入力の機能を使って、上記のファイルに自分の住所、学籍番号、
名前を記述しなさい。
- vi は挿入モードから直接終了することができるか ?
- vi はコマンドモードで文字入力が可能か ?
- vi でのキー入力'x'はモードによりどのように解釈されるか ?
- emacs で適当な文章を入力した後で、
emacs のコマンドを一通り実行して機能を確認しなさい。
- 数字とアルファベット 26 文字を並べた行 "0123456789abcdefg...xyz" を入力しなさい。
- emacs のリージョンをコピーする機能を使って、上記の行を 100 行コピーしなさい。
それを ログインネーム-emacs.txt (例 ed04000-emacs.txt)として記録しなさい。
- 日本語入力の機能を使って、上記のファイルに自分の住所、学籍番号、
名前を記述しなさい。
- gedit, vi または emacs でどれが最も使い易いと感じたか、その理由を文書にしなさい。
その後に続けて、
選択したエディタの主要な機能を自分が読んでわかるようにまとめて記述しなさい。
ファイル名は ログインネーム.txt (例 ed04000.txt)とする。
- GUI 環境でマウスを併用する Word, gedit などと、CUI 環境の vi, emacs について,
それぞれの長所、短所を考えて上記のファイルに記述しなさい。
4 UNIX, Linux の特徴 (第 2, 3 週)
4.1 UNIX, Windows の特徴と相違点 (p.22)
UNIX の特徴として以下の事柄を挙げることができる。
- 研究、開発用
- 1 台のマシンを複数の人が同時に使用することを前提としている。
- CUI, キャラクタベースのユーザインタフェースが基本
- データの形式はテキスト、文字データを中心にしており、
文字データを操作するコマンドが豊富に用意されている。
- 使い勝手はシンプルで、慣れると効率良く仕事ができるが、初心者には使い難い。
- 画像データ、音声データを扱う機能は現在でも少ない。
- 作業を自動化する仕組みが豊富に用意されている。
対する Windows の特徴として以下の事柄がある。
- 個人用、汎用、事務処理、趣味
- 1 台のマシンを一人で使用することを前提としている。
- GUI, グラフィックベースのユーザインタフェースが基本
- データの形式はテキスト、文字データ、バイナリデータのどれでも扱える。
標準のコマンドはあまり多くない。
- きれいな画面で直感的な操作が可能で初心者には使い易い。
マウスでの操作は慣れても効率が良くならない。
- 画像データ、音声データなどマルチメディア関係のデータを扱う機能は優れている。
- 作業を自動化する仕組みはほとんどない、人がマウスで操作する。
両者の相違点として様々なものがあるが、特に操作性の点では UNIX は初心者には使い難く
Windows は初心者でもある程度練習すれば使えるようになる。
一方熟練者にとっては UNIX は効率良く作業を行なう仕組みが豊富に用意されているが、
Windows にはそのような仕組みがあまりないといえる。
これらは何を重視するかにより生じている違いであり、それぞれの長所であり短所となっている。
4.2 Login, Logout (p.36)
UNIX, Linux は 1 台のコンピュータを複数のユーザが(必要であれば同時に)
使うことを前提として開発されているので、
「誰が」使用するかを必ず入力して個人認証を行う。
この操作を Login (Logon) と呼ぶ。作業を終了する時にはそのことを OS に通知する。
この操作を Logout (Logoff) と呼ぶ。
4.3 一般ユーザと特権(管理者)ユーザ (p.38)
UNIX, Linux のユーザ、使用者は、操作可能なコマンドやアクセス可能なファイル、
デバイスが異なる、一般ユーザと特権(管理者)ユーザに分かれる。
UNIX における特権(管理者)ユーザは標準的な名前 root と呼ばれる。
これらのユーザの違いは OS に対して持っている権限の違いと言える。
一般ユーザは通常の作業をするには十分な権限を持つが、
OS の重要な部分やファイルを操作する権限はない。
これにより、不注意や知識の不足による誤操作でシステムを壊してしまう恐れがなくなる。
特権(管理者)ユーザは、システムのあらゆる部分を操作できるが、
万一誤操作をすると簡単にシステムを壊してしまうことになる。
よって、特権(管理者)ユーザであっても、通常の仕事は必ず一般ユーザで行なう。
例
一般ユーザは重要なファイル、他人のファイルを見ることができない。
一般ユーザはシステムの動作に関連するファイルを消すことができない。
一般ユーザはデバイスを直接操作できない。
一般ユーザは OS を停止できない。
一般ユーザは特権(管理者)ユーザになれない。
4.4 パスワード (p.36,59)
個人認証では、使用する前にパスワードを入力させて登録された本人か確認する。
パスワードとはユーザがあらかじめ登録している数文字の文字列で、
本人しか知らない。本人しか知らないパスワードを正しく入力できれば、
本人と見なされる。よってパスワードは他人に知らせてはいけない。
パスワードは暗号化されて所定のファイルに記録されている。
4.5 シェル, Shell (p.64,115)
標準的なユーザインタフェースとして、キャラクタベースの「シェル」を使用する。
シェルを通して OS にコマンドの起動や様々な指示を与えることで作業を進める。
マウスを使わないで、キーボードから入力する文字ですべての指示を与えるため、
離れた場所のコンピュータをネットワーク経由で使うことができる。
例
% ssh luna.edu.isc.chubu.ac.jp
4.6 コマンド (p.45,66)
UNIX, Linux では多数のコマンドが標準で付属する。
個々のコマンドは比較的単純な機能しか持たず、単一のコマンドで複雑な処理はできない。
そのかわりに、各コマンドは他のコマンドと組み合わせて使用できるように、
データの入力、出力の仕組みが統一されている。複雑な処理を実現したいときは、
様々なコマンドを組み合わせて実現するのが一般的である。
例
ある日(仮に 10 月 3 日とする)、何人のユーザがこのコンピュータを
使用したか調べたいとする。利用者の記録は
% last
で調べることができる。
このコマンドに文字列検索のコマンド、
行数を数えるコマンドを組み合わせて、
% last | grep 'Oct 3' | wc -l
で回数が分かる。更に、
% last | grep 'Oct 3' | cut -f 1 -d ' ' | uniq | sort
とすると、重複した行を削除して正しい人数がわかる。
(※ Oct と 3 の間は空白文字が 2 個必要)
4.7 man, オンラインマニュアル (p.40,82)
UNIX, Linux では豊富なオンラインマニュアルを備えており、
わからないことはまずオンラインマニュアルで調べる。使用方法は、
% man 調べたい事柄
と入力する。調べたい事柄にはコマンドの名前、C 言語の関数名、
設定ファイル名などが指定できる。
man コマンドで次のページを見たい場合は、Enter や Space を入力する。
上下の矢印キーでも移動可能。終了は 'q' を入力する。
例
% man ls コマンド ls の機能や使い方を調べる
% man cat コマンド cat の機能や使い方を調べる
% man printf C 言語の関数 printf() の機能や使い方を調べる
% man hosts /etc/hosts 設定ファイルの機能や記述の仕方を調べる
4.8 練習問題
- Windows と UNIX, Linux との違いを何点か挙げなさい。
- login, logout が必要な理由を考えなさい。
- 一般ユーザと管理者ユーザが存在する理由を考えなさい。
- パスワードを決める際に気をつけることを考えなさい。
- パスワードの取り扱いで気をつける点を挙げなさい。
- UNIX のシェルはキーボードからの文字入力だけですべての操作ができるが、
それによりどのような利点があるか考えなさい。
- Windous の標準的なユーザインタフェースである、ビットマップディスプレイ、
マウス、アイコンやメニューを使用する GUI (Graphical User Interface) と、
UNIX, Linux の CUI (Character User Interface) について、それぞれの長所、
短所を考えなさい。
- 4.6 の例の日付を講義当日に変更して実行しなさい。その結果から、
その日に login した合計回数と人数を求めなさい。
- 4.7 の説明にしたがって、コマンド ls, cat, date, cal
の機能をオンラインマニュアルを利用して調べなさい。
5 データを記録、参照する仕組 (第 4, 5 週)
5.1 ファイルとディレクトリ (p.72,87)
多くの OS では、コンピュータ上で扱うデータを記録、
操作する単位はファイルと呼ばれる概念で表される。
ファイルを記録する場合に管理を容易にするためにディレクトリという仕組みが利用される。
ディレクトリは複数のファイルをまとめて一つの場所に置いておくことができる。
ファイルを整理したい条件に合わせて様々なディレクトリを用意して、
その中にファイルを記録する。
例
% ls /usr8/ed04
ed04001 ed04014 ed04030 ed04046 ed04058 ed04071 ed04083 ed04097 ed04109
ed04002 ed04016 ed04031 ed04047 ed04059 ed04072 ed04084 ed04098 ed04110
ed04003 ed04018 ed04032 ed04048 ed04060 ed04073 ed04086 ed04099 ed04111
ed04004 ed04019 ed04033 ed04049 ed04061 ed04074 ed04087 ed04100 ed04112
ed04005 ed04021 ed04035 ed04050 ed04062 ed04075 ed04088 ed04101
.
.
以下略
この例では 2004 年度入学の ed の学生が使用する個人用ディレクトリがまとめて登録されている
/usr8/ed04 という架空のディレクトリを例として表示している。
/ の下に usr8 があり、その下に ed04 があり、その下に個人用の ed04001, ed04002, ... があり、
複数の階層にわかれて管理されていることがわかる。
% ls /usr
X11 bin dpt games kerberos libexec opt share tmp
X11R6 dict etc include lib local sbin src
この例では / の下に usr というディレクトリがあり、その下のディレクトリが表示されている。
これらはすべて OS が管理、使用している領域で、各種プログラムや文書、設定ファイルなどが
様々なディレクトリに分かれて保存されている。
5.2 パス : ファイルの位置 (p.56,87)
ファイルやディレクトリの位置を表す情報をパスと呼ぶ。パスには / (ルート
ディレクトリ) からの位置を表す絶対パスと、現在のディレクトリ位置を起点
として表す相対パスがある。
よく使われる表記法として . は現在のディレクトリを、.. は一つ上の階層のディレクトリを、
~ はホームディレクトリを表す。
ホームディレクトリに戻る場合は次のどれかのコマンドを実行する。
% cd ホームディレクトリの絶対パス指定
% cd ホームディレクトリの相対パス指定
% cd ~
% cd
/ は最上位のディレクトリ(ルートディレクトリ)を表す。
例として、現在のディレクトリが /usr8/ed04/ed04000 とすると
(実際のディレクトリは % pwd で確認できる)、
/, usr8, ed04, ed04000 という 4 段階の階層構造になっている。
一つ上の階層は、絶対パスなら /usr8/ed04 となり、相対パスなら .. となる。
二つ上の階層は、絶対パスなら /usr8 となり、相対パスなら ../.. となる。
三つ上の階層は、絶対パスなら / となり、相対パスなら ../../.. となる。
現在のディレクトリが /usr8/ed04/ed04000 の場合、
別の年度の学生のディレクトリ /usr8/ed05/ed05000 は、
絶対パスならそのまま /usr8/ed05/ed05000 と表せ、
相対パスなら ../../ed05/ed05000 と表すことができる。
/usr は / の下の usr というディレクトリ(またはファイル)を表す。
usr がディレクトリかファイルかは名前を見ただけではわからないが、
属性を表示させてみるとわかる。
% ls -l /
を実行すると、多くの表示の中に
drwxr-xr-x 16 root root 4096 9月 25 15:42 usr/
と表示されるが、左端の d がディレクトリであることを表している。
もし通常のファイルであれば、
-rwxr-xr-x 16 root root 4096 9月 25 15:42 usr/
のように - が表示される。
以下はディレクトリを絶対パス、相対パスで指定して移動するコマンド指定の例である。
実際に試す時は usr8 や ed04 を実在するディレクトリに置き換える必要がある。
例
% pwd 現在のディレクトリを表示するコマンド
/usr8/ed04/ed04000
% cd ../../.. 上の上の上に移動、cd はディレクトリを移動するコマンド
% pwd
/ ルートディレクトリに移動したことがわかる
% cd ./usr8/ed05 相対パスで指定して、現在のディレクトリ下の usr8/ed05 に移動
% pwd
/usr8/ed05
% cd ../ed04/ed04000 相対パスで指定して、一つ上の階層にある ed04/ed04000 に移動
% pwd
/usr8/ed04/ed04000 もとに戻った
% cd /etc 絶対パス、/etc に移動
% pwd
/etc
% cd /usr8/ed04/ed04000 絶対パス指定
% pwd
/usr8/ed04/ed04000 もとに戻った
UNIX, Linux では OS を動作させるのに必要なファイルを、
標準的な名前の様々なディレクトリに記録している。
各ディレクトリの名前は UNIX 系の OS ではほぼ同じになっている。
UNIX, Linux では通常のデータを記録するファイルの他に、
周辺装置もファイルと同じ形式で表現され、操作できるようになっている。
5.3 ファイルの属性、アクセス制限 (p.92)
UNIX, Linux のファイル、ディレクトリは保護機能がしっかりしており、
誰がファイルを読めるか、書き込めるか、実行できるかという点を厳密に管理している。
以下の例はあるディレクトリでファイルの一覧を表示するコマンド 'ls -l'
を実行した時の出力である。
左端の drwx------ などの表示がファイルアクセスの設定を表している。
% ls -l
合計 100
drwx------ 2 naga denshi2 4096 7月 24 2001 2001list
drwx------ 2 naga denshi2 4096 7月 24 2002 2002list
-rw-r--r-- 1 naga denshi2 108 4月 23 2003 README
drwx------ 2 naga denshi2 4096 7月 24 2002 bin
-rw------- 1 naga denshi2 9311 7月 4 2000 chubu2000.txt
-rw------- 1 naga denshi2 1062 7月 4 2001 chubu2001.txt
-rw-r--r-- 1 naga denshi2 308 4月 30 2003 howtocopy
-rw-r--r-- 1 naga denshi2 4813 5月 14 2003 index.html
drwx------ 2 naga denshi2 4096 4月 16 2003 tmp
.
.
以下略
左から順に、ファイルモード(アクセス制限)・リンク数・所有者名・所有グループ名・
ファイルのバイト数・最終更新時の月・日・時・分(または年)・パス名(ファイル名)を表す。
最後の行を例として用い、各フィールドの表す内容を以下に示す。
drwx------ 2 naga denshi2 4096 4月 16 2003 tmp
(1) (2) (3) (4) (5) (6) (7) (8) (9)
- (1) はこのファイル(またはディレクトリ、以下同じ)
に設定されているアクセス制限を表している。
このフィールドは 10 文字で構成される。
左端の文字はファイルの種類を表し、d はディレクトリ、- は通常のファイルを表す。
2 文字目以降は 3 文字ずつがペアになり、ファイルの所有者、所有グループ、
その他のユーザのアクセス制限を表す。
- (2) は通常ファイルの場合 1、ディレクトリの場合 2、
ディレクトリ内にディレクトリが一つ増える毎に値が 1 増える。
例として、この値が 5 の場合は、
ディレクトリ内に 3 個のディレクトリがあることになる。
- (3) はこのファイルの所有者(ユーザ)を表す。
- (4) はこのファイルの所有グループを表す。
- (5) はこのファイルのサイズ(バイト数)を表す。
- (6),(7) はこのファイルの最終更新時の月日を表す。
- (8) はこのファイルの最終更新時刻を表す。6 カ月以上経過している場合は、
時刻の代わりに年が表示される。
- (9) はこのファイルの名前を表す。
以下は /etc に対してファイルの一覧を表示するコマンド 'ls -l'
を実行した時の出力である。
% ls -l /etc
合計 2064
-rw-r--r-- 1 root root 2456 8月 13 2003 DIR_COLORS
-rw-r--r-- 1 root root 2434 8月 13 2003 DIR_COLORS.xterm
drwxr-xr-x 4 root root 4096 7月 14 2004 FreeWnn
drwxr-xr-x 16 root root 4096 2月 15 2005 X11
-rw-r--r-- 1 root root 2562 1月 25 2003 a2ps-site.cfg
-rw-r--r-- 1 root root 15228 1月 25 2003 a2ps.cfg
-rw-r--r-- 1 root root 46 8月 28 18:05 adjtime
.
.
以下略
この例では、最下行の adjtime の最終更新時刻が最近だったため、
年の代わりに時刻が表示されている。
5.3.1 アクセス権、アクセス制限の詳細
UNIX, Linux では個々のユーザはどれかのグループに所属すると決められている。
グループの例として管理者のグループ、一般ユーザのグループ、
ゲストのグループなどが考えられる。所属するグループは一つでも複数でもよい。
ファイルのアクセス権、アクセス制限は各ファイルの所有者(ユーザ)、所有グループ、
その他のユーザの 3 種類に分けて設定される。
所有者の他に所有グループという分類があるのが特徴である。
アクセス権、アクセス制限は「パーミッション」と呼ばれることもある。
ここまでの説明中、「drwx------ がアクセス権、アクセス制限を表し、左から
2 文字目以降は 3 文字ずつがペアになり、ファイルの所有者、所有グループ、
その他のユーザのアクセス制限を表す。」という内容の記述があったが、
以下ではその詳細を示す。
drwx------ は、(1) d, (2) rwx, (3) ---, (4) --- という 4 個の部分に分解できる。
(1) の d はファイルの種類を示しているのでアクセス権には関係ない。
(2) の rwx はこのファイルを所有するユーザがどのようなアクセスが可能か示している。
r はこのファイルを読出す権利を持つ、w はこのファイルに書込む権利を持つ、
x はこのファイルを実行する権利を持つことをそれぞれ表す。
実行権については、ディレクトリの場合はコマンド cd で移動することが可能、
通常ファイルについては実行できる内容を持つファイルであれば実行できることを表す。
(3) の --- は各文字が読出権、書込権、実行権を表しているのは同じだが、
- になっているのでこのファイルを所有するグループのユーザには
いずれも許可されていないことを表す。
(4) も同様にすべて不許可を表し、その他のユーザはアクセスできないことを表す。
まとめると、このファイルの所有者は読出権、書込権、実行権をすべて有しているが、
所有するグループのユーザ、およびその他のユーザは一切アクセスできないことを表している。
以下ではアクセス権の設定例をいくつか示す。
- -rw------- は所有者以外は一切アクセスできない。
他人に見られたくないファイルはこのような設定にする。
- drwx------ は所有者以外は一切アクセスできないディレクトリになる。
x を付加しておかないと所有者でも cd で移動できない。
- -rw-r--r-- は他人も読むことが可能になる。
- drwxr-xr-x は他人が cd で移動できるディレクトリの設定になる。
- -r-------- は所有者が読み出すことだけできる。
間違って書き込むことを防止できる。
- -rwxrwxrwx は誰でも読み書き実行が可能になる。
内容を他人が勝手に変更することが可能。
- -rwxr-x--- は所有者は読み書き実行が可能、
グループに所属するユーザは読出し、実行が可能。
グループ内で共有する情報などが考えられる。
アクセス権の設定、変更は(次の章で出てくる)コマンド chmod で行なう。
アクセス制限は 3 桁の 8 進数で表現する。
例として、file1 を -rwxr-xr-x に設定したい場合は、
% chmod 755 file1
file2 を -rwx------ に設定したい場合は、
% chmod 700 file2
file3 を -rw-r--r-- に設定したい場合は、
% chmod 644 file3
となる。
5.4 練習問題
- 現在のディレクトリを表示するコマンド行を示しなさい。
- /usr/bin に絶対パス指定で移動するコマンド行を示しなさい。
- ホームディレクトリに戻るコマンド行を示しなさい。
- /usr/bin に相対パス指定で移動するコマンド行を示しなさい。
- ホームディレクトリに相対パス指定で戻るコマンド行を示しなさい。
- ホームディレクトリに絶対パス指定で戻るコマンド行を示しなさい。
- ホームディレクトリから別の学年のディレクトリ ed06 に相対パス指定で移動するコマンド行を示しなさい。
- ホームディレクトリから別の学年のディレクトリ ed06 に絶対パス指定で移動するコマンド行を示しなさい。
- /usr/share/man/man1 に、
ホームディレクトリからの相対パス指定で移動するコマンド行を示しなさい。
- cd /usr/share/doc を実行後に、/usr/share/man/man1
に相対パス指定で移動するコマンド行を示しなさい。
- -r-xr-x--- はどのようなアクセス制限を表すか説明しなさい。
- drwxr-x--- はどのようなアクセス制限を表すか説明しなさい。
- 所有グループに属する人は誰でも読み書きできる設定を示しなさい。
- 所有者は読み書き実行可能、
所有グループとその他のユーザは読み出しのみ可能な設定を示しなさい。
- ホームディレクトリにあるファイルのアクセス権の設定を調べなさい。
- 各回にファイルを提出するディレクトリ /usr7/denshi2/naga/午前午後/日付
のアクセス権の設定を調べなさい。
- エディタで何かファイル(仮に sample とする)を作成し、chmod 000 sample,
chmod 400 sample, chmod 600 sample, chmod 700 sample のようにアクセス権を
いろいろ設定しなさい。
それぞれの場合でエディタで開くことや書き換えが可能か試してみなさい。
- UNIX システムの標準的なディレクトリ /bin, /usr, /etc, /tmp, /var, /home
の用途を調べなさい。(教科書 p.53〜)
- /bin, /etc, /dev 中のファイルの所有者、アクセス権の設定を調べなさい。
なぜそのような設定になっているか理由を考えなさい。
6 コマンド (第 6, 7 週)
6.1 凡例
以下の記述で、[, ] で囲まれている部分は省略可能、書いても書かなくてもよいことを表す。
例として % mkdir dir [dir2 ...] の場合、
% mkdir dir
と指定すれば dir だけを作成し、
% mkdir dir dir2 % mkdir dir
と指定すれば dir と dir2 の 2 個のディレクトリを同時に作成できることを表す。
file, file2 などはファイルを、dir, dir2 などはディレクトリを表す。
コマンドを実行する時は実在するファイルやディレクトリで置き換える。
6.2 UNIX の代表的なコマンド
6.2.1 ディレクトリ操作 (p.103)
cd : 指定したディレクトリに移動する。
% cd dir
% cd // ホームディレクトリに移動
mkdir : ディレクトリを作成する。
% mkdir dir [dir2 ...]
rmdir : ディレクトリを削除する。
% rmdir dir [dir2 ...]
pwd : 現在のディレクトリを表示する。
% pwd
6.2.2 ファイル操作 (p.91,96)
ls : ファイルの一覧を表示する。
% ls
% ls -Flg -a dir // ファイルの詳細を表示
mv : ファイル/ディレクトリを移動する、名前を変更する。
% mv file file2 // ファイル名の変更
% mv file dir/file2 // ファイルを dir に移動して、ファイル名の変更
% mv file [file2 ...] dir // ファイルを dir に移動
% mv dir dir2 // dir を dir2 に移動、または名前の変更
※ 最後に書くのがファイル名だけだと名前の変更、別のディレクトリとファイル名を
指定すると移動と名前の変更を同時に行なう。ディレクトリだけだと移動。
最後の例では、dir2 が既存なら移動、存在しなければ名前の変更になる。
cp : ファイルをコピーする。
% cp file file2 // file を file2 という名前でコピー
% cp file [file2 ...] dir // file を dir にコピー
% cp -R dir [dir2 ...] dir3 // dir の中身も一緒に dir3 にコピー
rm : ファイルを削除する。
% rm file [file2 ...]
% rm -r dir [dir2 ...] // dir の中身も一緒に削除
% rm -i file // 対話的に確認しながら削除
find : ファイルを探して指定した処理をする。
% find dir -name "*.txt" -print // 条件に合うファイルの名前を表示
chmod : ファイルのアクセス権を設定する。
% chmod 644 file
% chmod u+rw,go=r-wx file // 8 進数以外にこのような記法もある。man chmod を見よ。
file : ファイルの種類を表示する。
% file file2 [file3 ...] // 最初の file はコマンド名、この例では file2 の
// 種類を表示する。
whereis : ファイルの場所を探す。
% whereis ls // コマンド ls のある場所を表示
% whereis -m cat // コマンド cat のマニュアルのある場所を表示
touch : ファイルのアクセス時刻と変更時刻を変える。
% touch file // file のアクセス日時を更新、存在しなければ新規作成
% touch -t 200510011234 file // アクセス日時を指定した値にする
6.2.3 テキストファイル操作 (p.96,103)
cat : ファイルを表示、縦方向に連結する。
% cat file // file の内容を画面に出力する。
% cat file [file2] // file2 を指定した場合は file に続けて出力する。
more : ファイルを 1 画面分ずつ表示する。
% more file
less : ファイルを 1 画面分ずつ表示する。後戻りが可能。
% less file
head : ファイルの先頭を表示する。
% head file
tail : ファイルの末尾を表示する。
% tail file
diff : 2 個のファイルの違いを調べる。
% diff file file2
grep : ファイルから指定した文字列を検索する。
% grep abc file // file から abc という文字列を含む行を探して表示する。
% grep 'abc def' file // "abc def" という文字列を対象にする
wc : ファイルのバイト数、語数、行数を数える。
% wc file // file のバイト数、語数、行数を表示する。
% wc -l file // file の行数を表示する。
uniq : ファイル内の重複行を調べて削除する
% uniq file
cut : ファイルから指定した部分を取り出す。
% cut -f 1 -d ' ' file // 空白文字を区切り文字として、各行の 1 番目の項目を取り出す
% cut -b 1-10 file // 各行の最初の 10 バイトを取り出す
paste : ファイルを横方向に連結する。
% paste file file2
sort : ファイルの内容を指定した項目により並び換える。
% sort file
% sort -k 2 file // 左から 2 番目の項目を基準に並び換える。
% sort +1 file // 左から 2 番目の項目を基準に並び換える。このような書き方も可能。
% sort -n file // 先頭の項目を数値として小さい順に並び換える。
% sort -b file // ソートする項目の先頭にある空白を無視する。
% sort -r file // 並び換えの順序を逆にする。
tr : 文字列を置換、削除する
% echo abcdefg | tr abc ABC // 試してみよう
% echo abcdefg | tr -d abc
% cat file | tr abcdefghijklmnopqrstuvwxyz opqrstuvwxyzabcdefghijklmn > file2
% cat file2
※ ファイルの暗号化
% cat file2 | tr opqrstuvwxyzabcdefghijklmn abcdefghijklmnopqrstuvwxyz > file3
% cat file3
※ 暗号化されたファイルの復号化
sed : テキストデータを処理する非対話的なエディタ
% echo abcdefg | sed s/abc/123/ // 試してみよう
6.2.4 ユーティリティ (p.177)
df : ディスクの使用量を表示する。
% df
du : ファイル、ディレクトリのディスク使用量を表示する。
% du
look : 指定した文字列を辞書から検索する。
% look word // word が辞書に登録されているか調べる。
man : オンラインマニュアルを表示する。
% man ls
% man 2 intro
passwd : パスワードを変更する。
% passwd
w : ログインしているユーザと、作業内容を表示する。
% w
who : ログインしているユーザを表示する。
% who
whoami : 自分が誰かを表示する。
% whoami
yes : 指定した文字列を連続して出力する。
% yes // y を無限に出力する
% yes 'Hello world.' // Hello world. を無限に出力する
% yes | rm -i *.txt // rm -i の確認に y を答え続ける
uptime : システムの稼働時間を表示する。
% uptime
last : 最近ログインしたユーザの記録を表示する。
% last
date : 日付と時刻を表示する。
% date
cal : カレンダーを表示する。
% cal // 現在の月のカレンダーを表示する。
% cal 10 2005 // 2005 年 10 月のカレンダーを表示する。
at : 指定した日時にプログラムを実行する。
% echo "ls" | at 20:14 // 20:14 に ls を実行する (セキュリティの関係で試せない)
% echo "ls" | at 20:14 101805
bc : 数値計算をする。
% echo "scale=10; 1+2*4/3" | bc -l // 試してみよう
% echo "scale=10; s(3.1416/2)" | bc -l // sin(pi/2) の表示
% echo "scale=10; 4*a(1)" | bc -l // 試してみよう
6.2.5 プロセス制御 (p.192)
kill : プロセスに様々なシグナルを送る。
% kill pid
% kill -HUP pid // ハングアップシグナルを送る
% kill -KILL pid // 強制終了のシグナルを送る
ps : プロセスの状態を表示する。
% ps -Al
% ps aux
top : 現在実行中のプロセスに関する情報を表示する。
% top
6.3 練習問題
- 上記のコマンドからいくつかを選んで、
オンラインマニュアルを利用しての代表的な機能を調べなさい。
調べた結果を簡潔にまとめて説明しなさい。
実際にそれらの機能を使用してみなさい。
- 次に示す機能を実現するコマンドの組み合わせを考えなさい。cat.txt, data.txt,
data2.txt, last.txt, ps.txt は指定されたディレクトリからコピーしなさい。
- tmp1, tmp2, tmp3, tmp4 というディレクトリを作成する
- tmp1 の中に sample1、tmp3 の中に sample3 というファイルを作成する
- tmp2 を削除する
- tmp3 を削除する
- tmp1/sample1 を sample2 というファイル名でコピーする
- sample1, sample2 を tmp4 に移動する
- sample2 のファイル名を sample3 に変更する
- tmp4/sample1,3 を tmp1 にコピーする
- ホームディレクトリ以下でファイル名が sample で始まるものを探して表示する
- sample1 のパーミッションを自分は読み書き実行可能に、
それ以外はすべて不許可に設定する
- sample3 のパーミッションを自分は読み書き実行可能に、
それ以外は読み出しだけ可能に設定する
- /etc/hosts のファイルの種類を調べる
- コマンド cat がある場所を調べる
- cat.txt, ps.txt を縦に連結して表示する
- cat.txt, ps.txt を横に連結して表示する
- cat.txt を一画面分ずつ表示する
- cat.txt の先頭を表示する
- cat.txt の末尾を表示する
- data.txt, data2.txt の違いを調べる
- data.txt 中に "5678" という文字列を含む行が何行あるか調べる
- cat.txt 中に "the" という文字列を含む行が何行あるか調べる
- data.txt が何行あるか調べる
- ps.txt から第 1 列のユーザ名だけを取り出す
- ps.txt に何人のユーザが含まれるか調べる
- ps.txt を PID の順番に並べ換える
- tr を使って cat.txt を暗号化する
- tr を使って暗号化された cat.txt を復号化する
- 過去に誰が login したか調べる
- 起動してからの稼働時間を表示する
- UNIX システムでいくつのプロセスが並行して動いているか調べる
- cat.txt の小文字をすべて大文字に変換する
- HDD の使用状況を調べる
- 自分が占有しているディスクの容量を調べる
- 単語 "organisation" の綴りが正しいか調べる
- 自分のマシンに誰がログインしているか調べる
- 10 分後にカレンダーを表示する。(現在試すことはできない)
- sin(30deg) の値を求める
7 シェルによる操作環境 (p.115) (第 8, 9 週)
UNIX, Linux で標準的なユーザインタフェースとして使用されるシェルには様々な種類がある。
広く使われている代表的なシェルとして bash, tcsh がある。
これらは古くからある bsh(sh), csh の機能を拡張して新しく作られた。
実習用の環境では tcsh が標準のシェルとして設定されている。
以下では tcsh の代表的な機能を順に解説する。
7.1 コマンドラインの編集、文字列補完 (p.144)
- emacs, vi 互換のコマンドでコマンド行の編集ができる。
- 編集コマンドのキーへの割り当ては bindkey で確認できる。
- 入力の途中で TAB キーを入力するとコマンドやファイル名を補完してくれる。
シェル変数 correct = all などの設定で有効になる。
- 入力の途中で Ctrl-d を入力するとコマンドやファイル名の候補を表示してくれる。
- コマンドやファイル名を間違って入力すると、正しいと思われる候補を教えてくれる。
シェル変数 autocorrect を設定することで有効になる。
例
% sl /usr/share/man/man1
と入力したところでコマンド名の間違いに気がついたら
Ctrl-a や Ctrl-p でカーソルを戻して修正できる。
% bindkey
で編集コマンドの確認ができる。
% set correct = all
% ls /usr/share/ma
まで入力して TAB キーを押すと補完がされる。
補完がされない時は Ctrl-d を入力すると候補が表示される。
% set autocorrect
% sl /usr/share/man/man1
と入力して RET キーを押すと、
CORRECT>ls /usr/share/man/man1 (y|n|e|a)?
と教えてくれる。
% sl /usr/share/mann/man1
でも大丈夫。
7.2 ファイル名の置換、字句解析 (p.143)
コマンドラインからファイル名を指定する場合、次の文字 *, ?, [, ], ~
は特殊な意味を持ち、これらを活用することでファイル名を簡潔に指定できる。
- * は 0 文字以上の任意の文字にマッチする。
- ? は任意の 1 文字にマッチする。
- [, ] で文字の範囲を指定できる。
- ~ はホームディレクトリを表す。
例
/usr には以下のファイル、ディレクトリがある。
% cd /usr
% ls
X11 bin dpt games kerberos libexec q! share tmp
X11R6 dict etc include lib local sbin src
% ls -d X*
X11 X11R6
% ls -d ???
X11 bin dpt etc lib src tmp
% ls -d [a-e]*
bin dict dpt etc
% ls ~/[a-z]*
ホームディレクトリの a 〜 z で始まるファイル、
ディレクトリが表示される
7.3 エイリアス (p.145)
エイリアスとはコマンドに別名を付ける機能で、長いコマンド、
複雑なコマンドに短いわかりやすい名前を付けたり、
頻繁に指定するオプションを含めて新しい名前を付ける時に使用する。
エイリアスの設定は以下の例に示すように、シェルの組み込みコマンド alias を使って、
alias 新しい名前 古い名前の順に指定する。
古い名前には複数の文字列を指定でき、オプションなどを含めることができる。
例
% alias
alias a alias
a h history
a more less
a ls ls -F
a ll ls -l
a la ls -a
a cls clear
a lo logout
a l look
a gv ghostview
a sc source $HOME/.cshrc
a ? whereis
エイリアスの設定を削除する時は unalias エイリアス名とする。
例
% unalias a
7.4 ヒストリ (p.141)
ヒストリはシェルから実行したコマンドの履歴を記録しておく機能で、
必要に応じて一覧を表示したり、過去に実行したコマンドを簡単な指定で再度実行できる。
シェルの組み込みコマンド history を実行すると、
過去に実行したコマンドの履歴を表示できる。
以下では history の出力例と、様々な方法で履歴中のコマンドを指定する方法を示す。
例
% history
1 18:41 emacs softa.xml
2 20:03 lo
3 15:09 h | grep startx | wc -l
4 15:09 h | grep lo | wc -l
5 15:09 h | more
6 15:27 sc
7 15:28 cat .history
8 19:53 startx
9 22:11 more .history
10 22:13 ? ls
11 22:13 su
12 22:13 exit
13 18:37 rsh farm from
14 18:37 ssh farm
15 18:41 cd xml
% !! // 直前に実行したコマンドを指定する。
cd xml
% !7 // ! と数値を指定することで履歴中のコマンドを指定する。
cat .history
% !c // ! とコマンドの先頭の数文字を指定して、
// 該当する文字から始まるコマンドを指定する。
cd xml
% !ca
cat .history
ファイル .history の内容が表示される。
% Ctrl-p // Ctrl-p, Ctrl-n で履歴中のコマンドを逆/順方向に
// たどって呼び出すことができる。
% cat .history
が表示され、再度 Ctrl-p を入力すると
% cd xml
が表示される。自分が呼び出したいコマンド、近いコマンドが
表示されたら適宜編集してEnter で実行できる。
7.5 シェル変数 (p.139)
シェル変数とはプログラミング言語における変数のような機能で任意の変数名と値を設定できる。
シェルではシェルスクリプト(プログラミング言語)により、
使用者が様々なコマンドや機能を組み合わせて複雑な処理を登録、実行することができる。
シェル変数はシェルスクリプト中で変数として設定、参照ができる。
シェル変数はあらかじめ名前と機能が定義されているものがあり、
シェルの動作や機能を設定するのに使用される。
シェル変数の設定状況はシェルの組み込みコマンド set で確認する。
% set
シェル変数の設定は
% set 変数名
または
% set 変数名 = 値
とする
シェル変数の設定の削除は
% unset 変数名
とする
シェルが自動的に設定するシェル変数は様々なものがある。
以下ではあらかじめ名前が登録されている、
特別な意味を持ったシェル変数の代表的なものを示す。
autocorrect コマンドラインでのコマンド名やファイル名の自動修正
cdpath cd が探索すべきディレクトリのリスト
correct コマンドラインでのスペル訂正の設定、値は cmd, complete, all
cwd カレントディレクトリのフルパス名
edit コマンドラインエディタ、対話型シェルではデフォルトで設定される
gid ユーザの実グループ ID
group ユーザのグループ名
history 記録しておくヒストリイベント数
home 起動したユーザのホームディレクトリ、~ の展開に参照する
ignoreeof Ctrl-d でシェルを終了しない設定
noclobber ファイルを壊さないための、出力リダイレクションの制限
path 実行可能なコマンドを探すディレクトリのリスト
uid ユーザの実ユーザ ID。
user ユーザのログイン名。
7.6 環境変数 (p.136)
環境変数はシェル変数とよく似た機能で任意の変数名と値を設定できる。
シェル変数と異なる点は、変数の値をシェルが定義したり参照するだけでなく、
そのシェルから起動されたプログラムに変数名と値が通知される点である。
よって環境変数を使うと、シェルから起動されたプログラムは、
実行される環境に関する様々な設定や情報を知ることができる。
様々な実行プログラムに関する設定をシェルの定義ファイルで統一して管理するために使用される。
環境変数もあらかじめ名前と機能が定義されているものがあり、
シェルの動作や機能を設定するのに使用される。
環境変数の設定状況はシェルの組み込みコマンド printenv で確認する。
% printenv
環境変数の設定は
% setenv 変数名
または
% setenv 変数名 値
とする
環境変数の設定の削除は
% unsetenv 変数名
とする
シェルが自動的に設定する環境変数は様々なものがある。
以下ではあらかじめ名前が登録されている、
特別な意味を持った環境変数の代表的なものを示す。
GROUP group シェル変数と同じ
HOME home シェル変数と同じ
HOST シェルが実行されているマシンの名前
HOSTTYPE シェルが実行されているマシンのタイプ、この変数は廃止される予定
LANG 優先的に使用される文字環境
MACHTYPE コンパイル時に決定されたマシンタイプ
OSTYPE コンパイル時に決定されたオペレーションシステム
PATH 実行可能ファイルを探すディレクトリ
PWD シェル変数 cwd に似てい
TERM term シェル変数と同じ
USER user シェル変数と同じ
VENDOR コンパイル時に決定されたベンダ名
環境変数をプログラムから読み出す場合は、
次のように文字列として読み出して必要な値を取り出す。
// gcc -o env env.c
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
int i;
for (i = 0; NULL != envp[i]; i++) printf("%s\n", envp[i]);
return(0);
}
7.7 設定ファイル .cshrc, .login (p.147)
シェル変数、環境変数、エイリアス、実行可能ファイルを探すパスの設定などは手動でも可能だが、
特定のファイルに記録しておくことでシェルの起動時に自動的に読み込ませることができる。
シェルの種類毎にファイル名が決まっているが、.cshrc, .tcshrc, .bashrc などがある。
また login した時の固有の設定を指定するための .login というファイルもある。
7.8 標準入出力、リダイレクト、パイプ (p.118,122)
UNIX, Linux の下で実行されるプログラム(コマンドを含む)には、
プログラムが処理対象のデータを外部から読み込む(入力する)対象と、
処理結果を外部に出力する対象として、標準入力、
標準出力と呼ばれる仕組みが用意される。
通常、標準入力にはキーボード、標準出力にはディスプレイが割り当てられているが、
それぞれ設定によって変更することもできる(リダイレクト)。
以下は標準入出力の機能の確認をするプログラムである。
例
// gcc -o io io.c
#include <stdio.h>
int main(void)
{
int i, j;
scanf("%d", &i);
scanf("%d", &j);
printf("%d\n", i + j);
return(0);
}
上記のプログラムをコンパイルして実行する。
% ./io
適当な数値を 2 行に分けて「キーボード」から入力すると、
3
5
加算した結果が「ディスプレイ」に表示される。
8
標準入力、標準出力を通常設定されているキーボード、ディスプレイ以外に振り向ける、
割り当て直す操作を「リダイレクト」という。
標準入力は 「<」 で、標準出力は 「>」 または 「>>」 でファイル、
その他の装置に変更できる。
例
入力するデータをあらかじめエディタでファイルに書き込んでおく。
% vi (または emacs) number.txt
% cat number.txt
5
7
このファイルを上記のプログラム io にリダイレクトの機能を使って入力すると
% ./io < number.txt
結果が表示される。
12
またリダイレクトの機能で結果をファイルに書き込むこともできる。
% ./io < number.txt > result.txt
% cat result.txt
12
次のように指定すると既存のファイルに結果を追記することもできる。
% ./io < number.txt >> result.txt
% cat result.txt
12
12
あるプログラムの標準出力を別のプログラムの標準入力に接続する仕組みを
「パイプ、パイプライン」という。パイプは縦棒「 | 」で指定する。
例
// gcc -o io2 io2.c
#include <stdio.h>
int main(void)
{
int i;
scanf("%d", &i);
printf("%d\n", i + i);
return(0);
}
上記のプログラムをコンパイルして実行する。
% ./io2
適当な数値を入力すると、2 倍した結果が表示される。
3
6
このプログラムをパイプで複数個接続して実行する。
% ./io2 | ./io2 | ./io2 | ./io2
この例では適当な数値を入力すると、16 倍した結果が表示される。
3
48
7.9 ジョブコントロール (p.125)
シェルでは複数のプログラムを並列に実行したり、
一部のプログラムの実行を中断して後から再開することができる。
その場合の個々のプログラムの実行状態を制御することをジョブコントロールという。
実行されるプログラムやコマンドを表す概念として「プロセス」と「ジョブ」がある。
プロセスとは OS が管理、認識する実行の単位で、
一般的なプログラムやコマンドは 1 プロセスとなる。
それに対してジョブとはシェルが管理、認識する実行の単位で、
単一のプロセスまたは複数のプロセスをパイプで接続したものとなる。
例
% cat file
は 1 プロセスかつ 1 個のジョブであり、
% cat file | sort | uniq | wc -l
は 4 プロセスから構成される 1 個のジョブとなる。
複数のジョブを並列に実行する場合、
foreground と background の 2 種類の状態がある。
foreground は、ある時点で端末からの入力を受け取るただ一つのジョブとなる。
background は端末からの入力から切り離されており、複数のジョブがこの状態で実行できる。
端末への出力は foreground, background どちらでも可能である。
端末からの入力が必要なジョブを background で実行すると、自動的に以下に示す中断状態になる。
シェルではジョブに対して様々な操作ができるが、
ジョブコントロールに関連したコマンドには以下のものがある。
- fg : ジョブを foreground で実行する。
- bg : ジョブを background で実行する。
- jobs : そのシェルで存在するジョブの一覧を表示する。
- Ctrl-z : ジョブの実行を中断する。
例
エディタ emacs または vi を起動する。
% emacs
エディタ実行中に Ctrl-z を入力すると、
実行を「中断」してシェルのプロンプトに戻る。
ここでジョブの一覧を表示すると、
% jobs
[1] + 中断 emacs
のように中断しているジョブがあることを示す。
エディタは終了しておらず編集内容を保っているので、
次のように実行を再開できる。
% fg %1
再び Ctrl-z でエディタを中断して、別のコマンド top を実行する。
% top
top も Ctrl-z で中断してジョブの一覧を表示すると、
% jobs
[1] - 中断 emacs
[2] + 中断(シグナル) top
のように中断しているジョブが二つあることを示す。
top を foreground に戻して終了する。
% fg %2
次にエディタを background で実行して jobs で確認すると、
% bg %1
[1] emacs &
% jobs
[1] + 中断(tty出力) emacs
端末からの入力を必要とするので自動的に中断される。
foreground に戻して終了する。
% fg %1
端末からの入力を必要としないジョブは複数個 background で実行できる。
また起動時に background での実行を指定することもできる。
例
// gcc -o fgbg fgbg.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i;
for (i = 0; i < 10; i++) {
printf("Loop count %d. \n", i + 1);
sleep(3);
}
return(0);
}
上記のプログラムをコンパイルして実行する。
% ./fgbg
終了する前に Ctrl-z で中断して background で実行する。
その後同じプログラムを新たに実行する。
起動時に background での実行を指定する時は & を付ける。
% ./fgbg &
表示されるメッセージから同時に実行していることがわかる。
ジョブはセミコロン ; で区切って、1 行に複数指定することができる。
その場合最初のジョブの実行が終了したら次のジョブに移る。
ジョブを括弧 (, ) で囲むと、
そのジョブを実行するための専用のシェルが起動されジョブが実行される。
この機能をサブシェルと呼ぶ。
例
% ./fgbg ; ./fgbg
とすると 2 個のジョブを左から順番に実行する。
ただし先のジョブを background に指定すると同時に実行される。
% ./fgbg & ; ./fgbg
カッコで囲むと専用のシェルが起動されそのシェルにより実行される。
% (./fgbg) ; ./fgbg
7.10 練習問題
- コマンドラインの編集機能を試してみなさい。シェル変数 correct や autocorrect
を設定した時の自動補完や修正の機能を試してみなさい。
- ファイル名の置換に関して、次に示すファイルを指定する表現を考えなさい。拡張子とは、
ファイル名の最後にピリオドに続けて指定するファイルの種類を示す文字列とする。
- 拡張子が txt のファイルすべて
- アルファベットの大文字で始まる名前のファイルすべて
- 5 文字のファイル名を持つファイルすべて
- 名前のどこかに abc を含むファイルすべて
- 名前の先頭が a で最後が b のファイルすべて
- 名前の先頭が a で最後が b の5 文字のファイル名を持つファイルすべて
- 名前のどこかに数字を含むファイルすべて
- 名前の先頭が a で拡張子が jpg のファイルすべて
- 名前の先頭が a で最後が jpg のファイルすべて
- 何らかの拡張子を名前に含むファイルすべて
- よく使うコマンドについて、自分で新しいエイリアスを登録してみなさい。
そのエイリアスでコマンドが実行できるのを確認した後、
エイリアスの設定を削除してみなさい。
- 以下のシェル変数の値がどのように設定されているか調べなさい。
cwd, gid, group, home, host, os, path, shell, term, uid, user
- シェル変数 abc に適当な値を設定しなさい。
次に変数 abc と値が設定されていることを確認しなさい。
次に変数 abc の定義を削除しなさい、そして変数 abc と値が削除されたことを確認しなさい。
- 以下の環境変数の値がどのように設定されているか調べなさい。
EDITOR, GROUP, HOME, HOST, HOSTNAME, HOSTTYPE, LANG, LOGNAME, MACHTYPE,
OSTYPE, PATH, PWD, SHELL, TERM, USER, VENDOR
- 環境変数 ABC に適当な値を設定しなさい。
次に変数 ABC と値が設定されていることを確認しなさい。
次に変数 ABC の定義を削除しなさい、そして変数 ABC と値が削除されたことを確認しなさい。
- .cshrc または .tcshrc および .login の内容を調べなさい。
- コマンド sort にファイル smalldata.txt を入力する方法を 3 種類示しなさい。
- 次に示す処理を実現するコマンドの組み合わせをリダイレクトやパイプを用いて示しなさい。
- ファイル data.txt の 1 列目の数値だけを取り出す。
- 1. の結果から文字 0 を含む行だけを取り出す。
- 2. の結果を値の小さい順に並べ換える。
- 3. の結果から重複する行を削除する。
- 4. の結果をファイル result.txt に書き込む。
- 4. の結果が何行あるか調べる。
- 4. の結果の先頭部分を表示する。
- エディタとコマンド top を起動して、
foreground と background で交互に切替えて実行してみなさい。
- 複数のコマンドをセミコロンで区切って実行して、実行の様子を確認しなさい。
- 次の 2 種類のコマンド列を実行した時の結果の違いを確認しなさい。
またそのような結果になる理由を説明しなさい。
% cd ; cd /usr/bin ; pwd ; pwd
% cd ; (cd /usr/bin ; pwd) ; pwd
8 パターン処理言語 awk (第 10, 11 週)
8.1 awk の概要、実行方法
パターン処理言語 awk (オーク, オウクと読む) は、
処理対象のテキストデータを 1 行ずつ読み込み、
指定した条件(パターンという)を満たす行に対して指定した処理(アクションという)を施す。
awk のプログラムはパターンとアクションの組を必要に応じて並べることで記述する。
プログラムの一般形は次のようになる。アクションは中括弧で囲む。
パターン { アクション }
awk のプログラムの記述は C 言語が参考にされており、
多くの場合で C 言語と同じ書き方ができるようになっている。
パターンとアクションはそれぞれ省略可能で、
パターンを省略するとすべてのレコードにアクションを施し、
アクションを省略するとパターンに一致したレコードを出力する。
awk では入力データの 1 行を「レコード」と呼び、
レコード内で区切り文字 (空白文字またはTAB) で分割される各単語を「フィールド」と呼ぶ。
awk の実行の仕方の例を次に示す。
awk のプログラムはコマンドラインから直接記述する方法と、
あらかじめファイルに作成しておいて実行時に指定する方法がある。
入力データのファイルを指定すればそこから、
指定しなければ標準入力から読み込む。
データファイルが以下のようになっているとする。
% head datafile
17767 9158 39017 18547 56401 23807 37962 22764 7977 31949
22714 55211 16882 7931 43491 57670 124 25282 2132 10232
8987 59880 52711 17293 3958 9562 63790 29283 49715 55199
50377 1946 64358 23858 20493 55223 47665 58456 12451 55642
24869 35165 45317 41751 43096 23273 33886 43220 48555 36018
53453 57542 30363 40628 9300 34321 50190 7554 63604 34369
62753 48445 36316 61575 6768 56809 51262 54433 49729 63713
44540 9063 33342 24321 50814 10903 47594 19164 54123 30614
55183 42040 22620 20010 17132 31920 54331 1787 39474 52399
36156 36692 35308 6936 32731 42076 63746 18458 30974 47939
以下の内容で programfile を用意しておく。このプログラムではパターンは
省略されており、1, 2 番目のフィールドを出力するアクションが指定されている。
% vi (または emacs) programfile
% cat programfile
{print $1,$2}
以下のように 4 種類の方法で実行できる。結果はすべて同じになる。
% awk '{print $1,$2}' datafile
% awk -f programfile datafile
% cat datafile | awk '{print $1,$2}'
% cat datafile | awk -f programfile
8.2 awk のプログラム : 変数
awk では一般のプログラミング言語と同様に変数を使用できる。
ユーザが定義する通常の変数は宣言をする必要がなく、
プログラム中で必要になった時にいきなり使うことができる。
awk の変数は整数や浮動小数点数、文字列などの「型」がなく、
同じ変数に数値や文字列をそのまま代入できる。
プログラム中では数値演算をする時には数として解釈され、
文字列に関する処理をする時には文字列として解釈される。
場合によっては誤動作の原因となるので注意が必要である。
対策として、数値用、文字列用の変数を完全に分けて使用することが考えられる。
例
以下は変数に数値、文字列を代入する例である。
数値の場合
% awk '{num=123; print num}' data
文字列の場合
% awk '{num="123"; print num}' data
ダブルクォート(")で囲むと文字列になる。
以下はフィールド変数を数値、文字列として比較する例である。
数値の場合
% awk '$1==123{print $1}' data
文字列の場合
% awk '$1=="123"{print $1}' data
% awk '$1 ~ /^123$/{print $1}' data
既定義変数としてあらかじめ名前と用途が予約されている「組み込み変数」がいくつかある。
また各フィールドを参照するための「フィールド変数」がある。
使用する機会が多い既定義変数は以下のものである。
- NR : 現在までに読み込んだレコードの数
- NF : 現在読み込んでいるレコード中のフィールドの数
- $0 : 現在読み込んでいるレコード全体
- $1 : 現在読み込んでいるレコードの 1 番目のフィールド
- $2 : 現在読み込んでいるレコードの 2 番目のフィールド
- $3 : 現在読み込んでいるレコードの 3 番目のフィールド
- 以下フィールドが終るまで同様
配列を使用することもできる。C 言語の配列と同様に a[5] のように表現する。
例
% awk '{for(i=1;i<=NF;i++){a[i]=$i; print a[i];}}' data
8.3 awk のプログラム : パターンの記述
パターンには以下の条件が指定できる。
- BEGIN
- END
- /正規表現/
- 式
- 正規表現や式の組み合わせ
BEGIN と END は特別なパターンで、
BEGIN は最初のレコードを読み込む前に行なう処理、
END は最後のレコードを処理した後の処理を指定するためにある。
例えば以下のプログラムでは BEGIN で変数の初期化、END で結果の出力を行なう。
例
% awk 'BEGIN{sum=0} {sum+=$1} END{print sum}' data
正規表現とは特定の文字列を指定する条件の記述法(後述)である。
式は算術演算や論理演算を組み合わせて表現される。
また正規表現やアクションで用いる文字列関数を含めることができる。
式の表現では以下の演算子が使用できる。一部を除いて C 言語と同じ表現が使用できる。
- ( ) 式のグループ化、括弧の内部が先に計算される
- $ フィールド参照 $i など、フィールド変数の表現と同じ意味を持つ
- ++ -- イ ンクリメント、デクリメント、前/後置可、C 言語と同じ意味
- ^ ** べき乗、C 言語にはこの演算子はない
- + - * / % 加算、減算、乗算、除算、剰余
- < > <= >= != == 関係演算子、C 言語と同じ意味
- ~ !~ 正規表現マッチ、詳しくは正規表現で取り上げる
- && || ! 論理 AND, OR, NOT
- = += -= *= /= %= ^= 通常の代入と演算後の代入
例
% awk '$1==10 {print}' data
% awk '$1*$2<=10 {print}' data
% awk '$1 ~ /^123$/ {print}' data
正規表現や式は単独で指定する他に、複数を組み合わせて指定することもできる。
評価の優先順位がわかり難い場合は必要に応じて括弧を加える。
例
% awk '($1==10) && ($2!=20) {print}' data
% awk '($1 ~ /^123$/) || ($2<20) {print}' data
% awk '!($1 ~ /^123$/) {print}' data
二つのパターン p1, p2 をカンマで区切って並べると、
p1 にマッチしてから p2 にマッチするまでという条件で範囲を指定できる。
% awk 'NR==3, NR==10 {print $1}' data
8.4 正規表現
正規表現とは特定の文字列を指定する条件の記述法で、
表現法は異なるがシェルと操作方法で取り上げたファイル名の置換機能と似ている。
正規表現はこの機能をより一般化して強化したものといえる。
awk における正規表現は前後をスラッシュで囲んで表現する。
以下に示す特定の文字(メタ文字)は本来のその文字として解釈されず、
文字の繰り返しや位置などを表す特別な意味を持つ。
メタ文字は \ . ^ $ [ ] | + - * ? ( ) { } である。
/ はメタ文字ではないが、正規表現の最初と最後を表すので、
通常の文字として扱いたい場合は注意が必要である。
各メタ文字の機能、正規表現の記述を以下に示す。
- c メタ文字ではない通常文字 c にマッチ
- \c 通常文字 c にマッチ、メタ文字をその文字本来の解釈にする
- . 改行を 含む任意の 1 文字にマッチ
- ^ 文字列の先頭にマッチ
- $ 文字列の終端にマッチ
- [abc...] abc... のいずれか 1 文字にマッチ
- [a-z] - は範囲を表す、例では小文字の abc...z の 1 文字にマッチ
- r1|r2 r1 または r2 にマッチ
- r1r2 r1 の直後に r2 が続くものにマッチ
- r+ r の 1 回以上の繰り返しにマッチ
- r* r の 0 回以上の繰り返しにマッチ
- r? r の 0 回または 1 回の繰り返しにマッチ
- (r) グループ化、括弧内の表現をまとめて扱う
例
レコード中に abc を含む。(場合にマッチしてそのレコードを出力する)
% awk '/abc/ {print}' data
レコード中に . を含む。(\ でメタ文字の機能を無効にしている)
% awk '/\./ {print}' data
レコード中に任意の 1 文字を含む。
% awk '/./ {print}' data
レコードの先頭が abc である。
% awk '/^abc/ {print}' data
レコードの最後が abc である。
% awk '/abc$/ {print}' data
レコードが abc である。(^,$ が両方あるので abc 以外の文字を含むことができない)
% awk '/^abc$/ {print}' data
レコードの先頭が a,b,c のどれかである。
% awk '/^[abc]/ {print}' data
レコードの先頭が abd, acd のどちらかである。
% awk '/^a(b|c)d/ {print}' data
レコードの先頭が abbb...bd, accc...cd, acbbd, abcbd などのどれかである。
% awk '/^a(b|c)+d/ {print}' data
ここまでの例ではマッチングの対象がレコード全体であったが、
次の演算子を使うことでマッチングの対象を単独のフィールド変数または変数に限定できる。
パターンの指定で
フィールド変数 ~ /正規表現/
変数 ~ /正規表現/
とすることで対象をフィールド変数、変数に限定する。
フィールド変数 !~ /正規表現/
変数 !~ /正規表現/
とすることで対象にマッチしないという条件も指定できる。
例
フィールド変数 1 に abc を含む。(場合にマッチしてそのレコードを出力する)
% awk '$1 ~ /abc/ {print}' data
変数 var に任意の 1 文字を含む。
% awk 'var ~ /./ {print}' data
フィールド変数 1 の先頭が abc でない。
% awk '$1 !~ /^abc/ {print}' data
変数 var の最後が abc でない。
% awk 'var !~ /abc$/ {print}' data
フィールド変数 1 が abc である。(^,$ が両方あるので他の文字を含むことができない)
% awk '$1 ~ /^abc$/ {print}' data
8.5 awk のプログラム : アクションの記述
アクションには以下の内容が指定できる。
パターンと同様に式や制御構文に正規表現を含むこともできる。
- 式
- print や printf などの出力文
- 制御構文 (if-else, for, while, do-while, break, continue など)
- 文字列関数 (length, substr など)
式、出力文の printf、制御構文は C 言語とほぼ同じ記述ができる。
複数の処理を指定したい場合は、セミコロン ; で区切って並べることができる。
式はパターンと同様の内容が記述できる。
出力文 print, printf の違いは、出力時のフォーマットを指定するかどうかで、
print は変数や数値を(フォーマット指定なしで)簡単に出力したい場合に使用する。
printf は桁数やフォーマットなどを指定して出力を整形したい時に使用する。
printf では C 言語と同様に %c, %s, %4d, %0.3f, %04x のような指定ができる。
例
% awk '{print $1,$2}' data
% awk '{printf("%d %4d\n",$1,$2);}' data
制御構文は以下のものが使用できる。記述の仕方はいずれも C 言語の場合と同じである。
- if (条件) {アクション} else {アクション}
- for (式;条件;式) {アクション}
- while (条件) {アクション}
- do {アクション} while (条件)
- break
- continue
例
% awk '{for (i=1;i<=NF;i++) sum+=$i; print sum;}' data
% awk '{if (0==NF%2) printf("even\n"); else printf("odd\n");}' data
% awk '{while ($1<10) {print $1; $1++;}}' data
文字列関数はいくつかあるが、ここでは代表的なものを 2 個だけ紹介する。
- length(s) 文字列 s の長さを返り値とする。
s を指定しないと $0 の長さを返り値とする。
- substr(s, i, n) 文字列 s の i 文字目から始まる最大 n 文字の文字列を返り値とする。
n を省略すると i 文字目以降の文字列が返り値となる。
例
% awk '10<length($1) {print $1}' data
% awk '{n=length($1); s=substr($1,3); print n, s}' data
8.6 サンプルプログラム
以下に簡単な awk のプログラムをいくつか示す。
各レコード(行)の 1 番目のフィールドを出力する
% awk '{print $1}' data
各レコードの 1,2 番目のフィールドを入れ換えて出力する
% awk '{print $2,$1}' data
10 行目(10 番目のレコード)を出力する
% awk 'NR==10{print $0}' data
% awk 'NR==10{print}' data
% awk 'NR==10' data
1 番目のフィールドの値が 10 でなければ、そのレコードを出力する
% awk '10!=$1{print $0}' data
% awk '10!=$1{print}' data
% awk '10!=$1' data
各レコード中のフィールドの和を求める
% awk '{sum=0; for (i=1;i<=NF;i++) sum+=$i; print sum}' data
1 番目のフィールドの和を求める
% awk 'BEGIN{sum=0} {sum+=$1} END{print sum}' data
行の総数(レコードの総数)を求める
% awk 'END{print NR}' data
フィールドの数が奇数か偶数かで異なるメッセージを出力する
% awk '{if (0==NF%2) printf("even\n"); else printf("odd\n");}' data
1 番目のフィールドの平均値を求める
% awk 'BEGIN{sum=0} {sum+=$1} END{print sum/NR}' data
(この例はこれまで最後の部分が誤って sum/NF となっていましたが、
2007/01/09 に正しい内容に修正した。)
文字列 "abc" を含むレコードを出力する
% awk '/abc/{print $0}' data
% awk '/abc/{print}' data
% awk '/abc/' data
各行に行番号を付ける、レコードに通し番号を付ける
% awk '{print NR,$0}' data
各行に 4 桁ずつの行番号を付ける、レコードに通し番号を付ける
% awk '{printf("%04d: %s\n",NR,$0);}' data
アルファベットだけから構成される単語を取り出して表示する
awk '{for (i=1;i<=NF;i++) if ($i ~ /^[A-Za-z]+$/) print $i;}' data
8.7 練習問題
- awk における出力で、print $1,$2 と print $1 $2 の違いを確認して説明しなさい。
- % awk 'NR==10{print $0}' data と
% awk 'NR==10{print}' data と
% awk 'NR==10' data の結果が同じになる理由を説明しなさい。
- % awk 'NR==1, NR==5 {print}' data と
% awk 'NR==5, NR==1 {print}' data の違いを確認して説明しなさい。
- awk の正規表現に関して、レコード、フィールドを次に示す条件で選択する
awk のプログラムの表現を考えなさい。
- 最初(1 番目)のフィールドが abc である
- 最初のフィールドの先頭が .txt にマッチ
- 最初のフィールドの先頭が .txt でない
- 最初のフィールドの最後が .txt にマッチ
- 最初のフィールドが 5 文字である
- 最初のフィールドの先頭が a で最後が b で 5 文字からなる
- レコードのどこかに数字を含む
- レコードのどこかに abc または cba を含む
- レコードの先頭がアルファベットの大文字で始まる
- レコードの先頭が a で最後が b である
- レコードの先頭が a でどこかに jpg を含む
- レコードの先頭が a で最後が jpg である
- レコードに括弧 ( または ) を含まない
- レコードに abc を 2 個以上含む
- レコードに abc を連続して 2 個以上含む
- 3 次元の座標データが data3d.txt に記録されている。
data3d.txt に対して以下の処理を awk で実行しなさい。
- 何行あるか求める
- "1234" という表現を含む行を表示する
- 1 次元目のデータで 100 未満のデータの個数を求める
- 2 次元目のデータの最大値、最小値を求める
- 3 次元目のデータの平均値を求める
- 3 次元目のデータで平均値より大きなデータの個数を求める
- コマンド ps の出力が ps.txt に記録されている。
ps.txt に対して以下の処理を awk で実行しなさい。
- 第 1 列のユーザ名だけを取り出す
- root が所有するプロセスの一覧と総数を求める
- 8 月 28 日に起動されたプロセスの一覧と総数を求める
- /usr/sbin にあるプログラムで起動されているものの一覧と総数を求める
- awk のオンラインマニュアルの一部が awk.txt に記録されている。
awk.txt に対して以下の処理を awk で実行しなさい。
- "the" という文字列を含む行を表示する
- 先頭が大文字で残りが小文字で表記されている単語を抽出して表示する
- 末尾にピリオドが付いている単語を抽出して表示する
- 最も長い単語を調べて表示する (ハイフン - で連結された単語は 1 語とする)
- アルファベットだけから構成される最も長い単語を調べて表示する
9 シェルスクリプト、作業の自動化 (第 12, 13 週)
9.1 シェルスクリプトとは
シェルスクリプトとは、通常シェルを対話的に使用して実行しているコマンドなどを、
プログラムのような形でファイルに記録しておき、
必要な時に呼び出して実行するための仕組みである。
シェルスクリプトは様々な制御構文を持つインタプリタ言語であり、
登録したコマンドを順番に実行するだけではなく、条件判断や繰り返し、
変数によるデータの記憶も可能となっている。
シェルスクリプトではこれまでに取り上げた様々な内容 (5 章 データを記録、参照する仕組み、
6 章 コマンド、7 章 シェルによる操作環境、8 章 パターン処理言語 awk)
をシェルスクリプトの内部から利用することが可能である。そのため、
コマンドや awk などのプログラミング言語で実現した方が簡単な処理はそれらを用いて実現し、
ファイル操作はシェルが備えている強力な機能を利用して実現し、
それ以外の制御構造をシェルスクリプトのインタプリタ言語で記述するといった感じで、
それぞれの便利/強力な機能をうまく組み合わせることで、
ある程度複雑な処理でも簡潔に表現、記述することができる。
シェルにはいくつかの種類があり、シェルスクリプトが備える機能もそれぞれ異なるが、
慣例としてシェルスクリプトは sh (bsh, Bourne shell と表現することもある) が備える
インタプリタ言語の文法で記述し、sh で実行することが多い。
この章でも sh のインタプリタ言語の文法を取り上げ、解説や例も sh に合わせて記述する。
なおここではシェルスクリプトのすべての機能は取り上げられないので、
主要な機能に絞って説明する。
以下では簡単な例として、同一の処理をシェルから対話的に実行する場合と、
シェルスクリプトとして記述してから実行する場合の手順を示す。
処理の内容は、/bin に置かれているコマンドの中から、サイズが
100 byte 未満のものだけを取り出して表示する。
対話的に実行する場合は次のように書ける。
% ls -l /bin | awk '$5<100{print}'
シェルスクリプトとして実行する場合は、まずエディタを使って
ファイルに実行する内容を書く。ファイル名は仮に sample.sh
とする。
% vi (または emacs) sample.sh
#!/bin/sh
ls -l /bin | awk '$5<100{print}'
ファイルに実行権を付加する。
% chmod 700 sample.sh
または
% chmod u+x sample.sh
これで実行できる。
% sample.sh
この例だけを見ると、シェルスクリプトは非常に手間がかかるように見えるが、
何回も実行する場合はシェルスクリプトの方が楽になる。
対話的に実行する場合は毎回必ず次のように書く必要がある。
% ls -l /bin | awk '$5<100{print}'
これに対して、シェルスクリプトは一旦作成してしまえば名前の
指定だけで実行できる。
% sample.sh
また数行に渡るような複雑な処理を、対話的に記述して実行するのは難しいので、
その場合もシェルスクリプトの仕組みを利用することが多い。
9.2 変数、パラメータ
シェルスクリプト内で値を覚えておく仕組みがパラメータで、
名前の付いているパラメータが変数となる。
シェルスクリプトで使用する変数は、整数や文字などの型はなく、事前の宣言も必要ない。
必要になった時にいきなり使用することができる。
変数に値を代入する時は'='を使う。制約として、=の前後に空白文字を入れてはいけない。
変数名には、アルファベット、数字、アンダスコア (_) のみが使える。
ただし、最初の文字に数字は使えない。
変数の内容を参照する時は変数名の前に $ を付ける。この操作をパラメータの展開と呼ぶ。
以下の例 sample2.sh では、変数名に $ を付けた場合と付けない場合の出力の違いを示す。
echo は変数や文字列を出力するシェルのコマンドである。
% vi (または emacs) sample2.sh
#!/bin/sh
abc=def
echo abc
echo $abc
% chmod 700 sample2.sh
% sample2.sh
ユーザが定義する変数の他に、
シェル内部であらかじめ内容や機能が決められているパラメータがある。
以下に代表的なパラメータを示す。$*, $0, $1, $2 は位置パラメータと呼ぶ。
$# シェルスクリプト起動時に指定されたコマンドライン引数の個数
$* 個々のコマンドライン引数
$0 シェルスクリプトの名前
$1 1 個目のコマンドライン引数
$2 2 個目のコマンドライン引数
.
.
.
コマンドライン引数とは、
シェルスクリプト動作時に空白文字で区切って同時に指定する文字列のことで、
以下の例の abc や 10 が該当する。
シェルスクリプトではコマンドライン引数を扱うための変数として、
位置パラメータが用意されている。
% sample.sh abc 10
以下の例 sample3.sh, sample3b.sh では、$#, $0, $1, $* の機能を示す。
コマンドライン引数の個数や内容を表示する。
% vi (または emacs) sample3.sh
#!/bin/sh
echo $#
echo $0
echo $1
echo $2
% chmod 700 sample3.sh
% sample3.sh aaa bbb ccc ddd
下記の例で使われている for ループの説明は、後に出てくる制御構造の項にあるので、
必要ならそちらを参照する。
% vi (または emacs) sample3b.sh
#!/bin/sh
for str in $*
do
echo $str
done
% chmod 700 sample3b.sh
% sample3b.sh aaa bbb ccc ddd eee fff ggg hhh
変数名の範囲を明確に指定するために、必要な場合は変数を中括弧 {, } で囲む。
以下の例 sample4.sh, sample5.sh では、
中括弧 {, } を付けた場合と付けない場合の出力結果の違いを見ることができる。
% vi (または emacs) sample4.sh
#!/bin/sh
abc=111
abcd=222
echo $abcd
echo ${abc}d
% chmod 700 sample4.sh
% sample4.sh
% vi (または emacs) sample5.sh
#!/bin/sh
echo $10
echo ${10}
% chmod 700 sample5.sh
% sample5.sh 111 222 333 444 555 666 777 888 999 aaa
9.3 コマンド置換
シェルスクリプト内でコマンドを実行する場合に、次のように指定することで、
コマンドを書いた位置でコマンドの実行結果を置き換えることができる。
実行結果で置き換えたいコマンドをバッククォート (`) で囲む。
この機能を使うことで、コマンドの結果を一時ファイルに記録することなく、
次の処理で直ちに利用することができる。
以下の例 sample6.sh では、通常のコマンド date の出力を変数 abc に代入して、
その後利用する例となっている。
コマンド date を端末エミュレータから単独で実行して、結果を先に見ておいてもよい。
% vi (または emacs) sample6.sh
#!/bin/sh
abc=`date`
echo $abc
echo $abc | awk '{print $4}'
% chmod 700 sample6.sh
% sample6.sh
9.4 引用、クォート
引用とは特殊な意味を持つ文字や単語 (演算子、空白、キーワードなど)
の意味を打ち消すために用いる指定である。
引用には、シングルクォート文字のペアを使う方法、
ダブルクォート文字のペアを使う方法、
バックスラッシュ文字を使う方法の 3 種類がある。
○ シングルクォート文字
シングルクォート (') のペアで囲まれた文字は、すべてその文字その
ままとして扱われる。ただしシングルクォートだけは別で、
シングルクォートで囲った文字列の中にシングルクォートを含めること
はできないという制約がある。
○ ダブルクォート文字
ダブルクォート (") のペアで囲まれた文字は、ドル記号文字 ($) 、バック
クォート文字 (`) 、バックスラッシュ文字 (\) を除き、すべてその文字
そのままとして扱われる。
○ バックスラッシュ
バックスラッシュ (\) は、その後ろの 1 文字を、文字そのままとして
扱うように指示する。
以下の例 sample7.sh では、クォート無し、シングルクォート、
ダブルクォートの 3 種類で出力がどう変化するか比較することができる。
% vi (または emacs) sample7.sh
#!/bin/sh
abc=`date`
echo $*
echo `date`
echo $abc
echo '$*'
echo '`date`'
echo '$abc'
echo "$*"
echo "`date`"
echo "$abc"
echo '$*'
echo "$*"
echo '"$*"'
echo "'$*'"
% chmod 700 sample7.sh
% sample7.sh aaa bbb ccc
9.5 制御構造
9.5.1 if
シェルスクリプトの if は指定した条件を満たした時に処理を行なう。
C 言語の if とほぼ同じ機能を持つが、記述の仕方が一部異なるので注意する。
以下の例 sample8.sh では、起動時に指定するコマンドライン引数の個数の違い
(2 個未満、3 個未満、3 個以上)を if 文で判定して、出力するメッセージを変化させている。
% vi (または emacs) sample8.sh
#!/bin/sh
if [ $# -lt 2 ]
then
echo 111
elif [ $# -lt 3 ]
then
echo 222
else
echo 333
fi
% chmod 700 sample8.sh
% sample8.sh aaa
% sample8.sh aaa bbb
% sample8.sh aaa bbb ccc
$# はシェルスクリプト起動時に指定したコマンドライン引数の個数である。
elif は else if の意味を表す。最後は fi で閉じる。
角括弧 [, ] で囲まれた部分が条件を表す。
[ を使う場合は後ろの ] は省略できない。
-lt は数として比較する時の < を表す。
if の条件の部分は角括弧 [, ] で囲まれているが、
[ はもともと test というコマンドであり [ はその別名である。
よって条件の部分は 2 種類の書き方があり、全く同じ動作をする。
以下にその例を示す。
sample8b.sh ではコマンドライン引数の個数を判定してメッセージを表示する。
% vi (または emacs) sample8b.sh
#!/bin/sh
if [ $# -eq 0 ]
then
echo no option 1
else
echo some options 1
fi
if test $# -eq 0
then
echo no option 2
else
echo some options 2
fi
% chmod 700 sample8b.sh
% sample8b.sh
% sample8b.sh aaa bbb
以下に指定できる条件の代表的なものを示す。
file はファイル名、str は文字列、int は整数、exp は式を表し、
それぞれ定数または変数を指定できる。
-d file file がディレクトリである
-f file file が通常のファイルである
-r file file がプロセスで読み出し可能である
-w file file がプロセスで書き込み可能である
-x file file がプロセスで実行可能である
-s file file のサイズが 0 でない
-------------------------------------------------------
str str が空でない
-n str str が空でない
-z str str が空である
str = str2 str と str2 が等しい
str != str2 str と str2 が等しくない
-------------------------------------------------------
int -eq int2 int と int2 が等しい
int -ne int2 int と int2 が等しくない
int -ge int2 int >= int2
int -gt int2 int > int2
int -le int2 int <= int2
int -lt int2 int < int2
-------------------------------------------------------
exp exp が真である
! exp exp が偽である
exp -a exp2 exp と exp2 の論理積, AND
exp -o exp2 exp と exp2 の論理和, OR
以下で条件の書き方の実例を示す。
sample8c.sh ではファイルの様々な属性を調べて表示する。
/etc/aliases は /etc にある設定ファイルの一つである。
% vi (または emacs) sample8c.sh
#!/bin/sh
if [ -d $1 ]
then
echo $1 is a directory
fi
if [ -f $1 ]
then
echo $1 is a file
fi
if [ -r $1 ]
then
echo $1 is readable
fi
if [ -w $1 ]
then
echo $1 is writable
fi
% chmod 700 sample8c.sh
% sample8c.sh /etc/aliases
次の例 sample8d.sh では文字列の比較をする。
$1 が空文字列か判定する、その後 $1 が存在する場合は aaa と一致するか判定する。
% vi (または emacs) sample8d.sh
#!/bin/sh
if [ -z $1 ]
then
echo '$1' is empty
fi
if [ $# -ge 1 ]
then
if [ $1 = aaa ]
then
echo '$1' is aaa
fi
fi
% chmod 700 sample8d.sh
% sample8d.sh
% sample8d.sh aaa
% sample8d.sh bbb
次の例 sample8e.sh では数値の比較をする。
% vi (または emacs) sample8e.sh
#!/bin/sh
if [ $1 -eq 5 ]
then
echo $1 is $num
fi
num=5
if [ $1 -ne $num ]
then
echo $1 is not $num
fi
if [ $1 -gt $num ]
then
echo $1 is greater than $num
fi
if [ $1 -lt $num ]
then
echo $1 is later than $num
fi
% chmod 700 sample8e.sh
% sample8e.sh 3
% sample8e.sh 5
% sample8e.sh 7
次の例 sample8f.sh では複数の条件を論理演算で結合する。
% vi (または emacs) sample8f.sh
#!/bin/sh
num=5
if [ $1 -ne $num ]
then
echo $1 is not $num
fi
if [ ! $1 -ne $num ]
then
echo $1 is not not $num
fi
if [ $1 -eq 3 -a $2 -eq 5 ]
then
echo $1 is 3 and $2 is 5
fi
if [ $1 -eq 3 -o $2 -eq 5 ]
then
echo $1 is 3 or $2 is 5
fi
% chmod 700 sample8f.sh
% sample8f.sh 3 3
% sample8f.sh 5 5
% sample8f.sh 3 5
% sample8f.sh 7 5
9.5.2 for
シェルスクリプトの for ループは指定した回数の繰り返しではなく、
変数に指定した文字列のリストから順に 1 個ずつ値を代入して、
各値に対して処理を行なう。
一連のファイルに対して同じ処理を繰り返したい時に便利に使える。
以下の例 sample9.sh では、曜日を表す文字列をリストとして for 文に指定して、
順に 1 個ずつ取り出し出力する。
% vi (または emacs) sample9.sh
#!/bin/sh
for day in Sunday Monday Tuesday Wednesday Thursday Friday Saturday
do
echo $day
done
% chmod 700 sample9.sh
% sample9.sh
以下の例 sample10.sh では、/etc にある a から始まるファイル名のファイルをすべて指定して、
順に 1 個ずつ取り出して if 文によりファイルかファイル以外か判定した後にメッセージを出力する。
/etc/a* は 7.2 ファイル名の置換、字句解析で取り上げた機能を利用している。
このように for ループを用いると、あるディレクトリにある、
特定の名前にマッチするファイルだけを取り出して操作することができる。
% vi (または emacs) sample10.sh
#!/bin/sh
for file in /etc/a*
do
echo -n $file, " "
if [ -f $file ]
then
echo normal file
else
echo directory or something
fi
done
% chmod 700 sample10.sh
% sample10.sh
9.5.3 while
シェルスクリプトの while は指定した条件を満たす間処理を繰り返す。
C 言語の while とほぼ同じ機能を持つ。
以下の例 sample11.sh では、シェルスクリプト内で整数をカウントして
0 から 9 まで表示する。expr は数の計算を行なうコマンドである。
一定回数だけ処理を繰り返したい場合はこのように記述できる。
% vi (または emacs) sample11.sh
#!/bin/sh
num=0
while [ $num -lt 10 ]
do
echo $num
num=`expr $num + 1`
done
% chmod 700 sample11.sh
% sample11.sh
9.5.4 break
break は while または for ループの繰り返しを終了する。
C 言語の break とほぼ同じ機能を持つ。
以下の例 sample12.sh では、
コマンドライン引数に skip が現れたらそれ以後の表示をしないという動作をする。
% vi (または emacs) sample12.sh
#!/bin/sh
for str in $*
do
if [ $str = skip ]
then
break
fi
echo $str
done
% chmod 700 sample12.sh
% sample12.sh aaa bbb ccc ddd skip eee fff
9.5.5 continue
continue は while または for ループの次の繰り返しに制御を移す。
C 言語の continue とほぼ同じ機能を持つ。
以下の例 sample13.sh では、
コマンドライン引数に skip が現れたらその場合だけ表示をしないという動作をする。
上記 sample12.sh の動作と比較すると両者の違いがわかる。
% vi (または emacs) sample13.sh
#!/bin/sh
for str in $*
do
if [ $str = skip ]
then
continue
fi
echo $str
done
% chmod 700 sample13.sh
% sample13.sh aaa bbb ccc ddd skip eee fff
9.6 ファイル名の操作
ここで取り上げるファイル名を操作するコマンド basename と dirname は、
シェルスクリプト自体が備える機能ではないが、
シェルスクリプトでファイル名を操作する場合によく使われ大変便利なものなので合わせて説明する。
コマンド basename はディレクトリを含んだファイル名から、
ディレクトリ部分を取り除いた名前を返す。
またファイル名から取り除きたい文字列を指定した場合は、
ファイル名から指定した文字列を取り除いた名前を返す。
コマンド dirname はディレクトリを含んだファイル名から、
ファイル名を取り除いた名前を返す。
以下の例 sample14.sh では、指定したディレクトリ /etc にある a から始まるファイルに対して、
basename と dirname がどのように働くか見ることができる。
basename を使うとファイル名だけ取り出せ、拡張子を取り除くこともできる。
逆に dirname を使うとディレクトリを表す部分だけ取り出すことができる。
% vi (または emacs) sample14.sh
#!/bin/sh
for file in /etc/a*
do
echo $file
echo `basename $file`
echo `basename $file .cfg`
echo `dirname $file`
echo ------------------------------------
done
% chmod 700 sample14.sh
% sample14.sh
9.7 シェルスクリプトの例
以下では様々な処理を実現するシェルスクリプトの具体的な例を示す。
9.7.1 大文字の拡張子 JPG を小文字の jpg に変更する
Windows で作成したファイルは拡張子が大文字になる場合があるが、
拡張子を小文字に変換する。
ディレクトリ内の拡張子が JPG のファイルを一括して変換する。
評価用の仮のファイルを作成する
% touch f001.JPG f002.JPG f003.JPG f004.JPG f005.JPG
% vi (または emacs) sample15.sh
#!/bin/sh
for file in *.JPG
do
mv $file `basename $file JPG`jpg
done
% chmod 700 sample15.sh
% sample15.sh
% ls
9.7.2 一定の形式のファイル名で通し番号を付けてファイルを作成する
統一された名前(仮に data とする)に通し番号を付けたファイル名で一連のファイルを作成する。
% vi (または emacs) sample16.sh
#!/bin/sh
num=1
while [ $num -lt 20 ]
do
num2=`echo $num | awk '{printf("%04d",$1);}'`
touch data$num2.txt
num=`expr $num + 1`
done
% chmod 700 sample16.sh
% sample16.sh
% ls
9.7.3 デジタルカメラの画像ファイルの名前を内容がわかるファイル名に変更する
デジタルカメラで撮影した画像ファイルが非常にたくさんある。
以下の例のように内容がわかるファイル名に変更する。
DCN00001.jpg → ryokou0001.jpg
事前に作成するファイル名の部分を書き換えた sample16.sh を利用して、
DCN00001.jpg の形式で通し番号のファイルを数十枚作成しておく。
% vi (または emacs) sample17.sh
#!/bin/sh
name=ryokou
for file in *.jpg
do
num=`basename $file .jpg`
num2=`echo $num | awk '{printf("%s",substr($1,5));}'`
mv $file ${name}${num2}.jpg
done
% chmod 700 sample17.sh
% sample17.sh
% ls
9.7.4 ls の結果を日時をファイル名にしたファイルに記録する
% vi (または emacs) sample18.sh
#!/bin/sh
ls -l > `date +%Y%m%d%H%M%S`.ls
% chmod 700 sample18.sh
% sample18.sh
9.7.5 複数のファイルで特定の単語を含む行数の一覧表を作成する
複数のファイルの各行から指定した単語を含む行を抜き出して行数の数える。
その結果をファイル名と合わせて表示する。
あらかじめ /usr7/denshi2/naga/DATA から awk.txt, cat.txt, cp.txt,
kill.txt, ls.txt, mkdir.txt, mv.txt, ps.txt
を自分のディレクトリにコピーしておく。
% vi (または emacs) sample19.sh
#!/bin/sh
if [ $# -lt 1 ]
then
echo Usage: $0 word
exit
fi
word=$1
for file in *.txt
do
echo -n $file
grep $word $file | wc -l
done
% chmod 700 sample19.sh
検索する単語を仮に"the"とする
% sample19.sh the
9.7.6 学生の出席日数を数える
毎回の実習に出席した学生が出席確認用のファイルを作成するので、
そのファイルを集計して学生の出席日数を数える。
あらかじめ /usr7/denshi2/naga/DATA からファイル 2006.tar
を自分のディレクトリにコピーしておく。
その後、
% tar xvf 2006.tar
を実行しておく。
% vi (または emacs) sample20.sh
#!/bin/sh
for dir in 2006/????
do
cd $dir
ls ex* > ../`basename $dir`.dat
cd ../..
done
cat 2006/????.dat | sort | \
awk '{if (last != $1) {last=$1;printf("%d\n%s ",num,$1);num=1;}
else num++;}
END{printf("%d\n",num);
}' | awk '1<NR' > 2006/result.dat
cat 2006/result.dat
% chmod 700 sample20.sh
% sample20.sh
結果は 2006/result.dat に記録されているので、
一旦答を求めたら次からは
% less 2006/result.dat
などでファイルの内容を表示すればよい。
9.8 練習問題
- 次の機能を持つシェルスクリプトを記述しなさい。
- コマンドライン引数の個数が1個の場合とそうでない場合で、
異なるメッセージを表示する。
- コマンド % ps aux の出力から、
所有者が自分になっているプロセスを取り出して表示する。
- コマンドライン引数を1個指定したときに、$1=??? と表示する。
??? には $1 の値が入る。
- コマンド date の出力から時間の部分だけ取り出して表示する。
- コマンド date の出力から何月何日の部分だけ取り出して表示する。
- コマンドライン引数としてファイル名を指定したときに、
ファイルかディレクトリか区別して表示する。
- コマンドライン引数としてファイル名を指定したときに、
実行可能かどうか区別して表示する。
- 仮想学科 ex の 2007 年度から 2012 年度までの各年度の学生の、
個人情報と期末試験の成績がファイルに記録されている。
これらのデータに対して次の処理を行ない結果を求めなさい。
項目の内容は左から順に、学籍番号、性別、出身県、年齢、身長、体重、
国語、算数、理科、社会、英語の点数である。
データが記録されているファイル ex07.dat ex08.dat ex09.dat ex10.dat
ex11.dat ex12.dat は、/usr7/denshi2/naga/DATA から
自分のディレクトリにコピーしなさい。
- 人数が一番多い年度はいつか。
- 愛知県出身の学生が一番多い年度はいつか。
- 女性が一番多い年度はいつか。
- 21 歳の学生が一番多い年度はいつか。
- 平均身長が一番高い年度はいつか。
- 男性の平均身長が一番高い年度はいつか。
- 平均体重が一番重い年度はいつか。
- 国語の最低点が一番高い年度はいつか。
- 算数の平均点が一番低い年度はいつか。
- すべての年度を通して最も身長が高い学生は誰か。
- すべての年度を通して 5 科目の合計得点が最も高い学生は誰か。
- すべての年度を通して平均点が最も高い科目は何か。
10 OS が備える主要な機能
10.1 カーネル
10.2 プロセス、スケジューリング
10.3 メモリ管理、仮想記憶
10.4 ファイルシステム
10.5 システムコール
10.6 ユーザインタフェース
10.7 入出力、割り込み
10.8 通信、ネットワーク
10.9 練習問題