第13章:FAQ

始めに

この章は、今までの総まとめって感じで、一問一答になっており、25個ほど質問があります。1つ1つブログ全部書き出してしまうと、この本の内容をすべて転記することになってしまい、この本の作者に悪い気がしますので、まとめるのはやめときまする。

終わりに

これで、何とか「入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界」が終わりでございます。第10章のスクリプトサンプルは、時間がかかる割に必要性が薄いのもあったので、必要になったときに読み返して行こうと思っております。
とりあえず、「入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界」を一通り読み終わって、シェルスクリプトの基本を少し理解できるようになったと思うので、これからは毎日少しずつシェルスクリプトを書いて、UNIXを勉強していきたいと思いまする。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第12章:汎用性

ここは、また実際にいろんなUNIX系のシステムを使うようになったら見ようと思います。ひよっこのわたくしにはまだ早いですな。。。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第11章:デバックの手順・手法

始めに

C言語とかを少しやっていたこともあり、コンパイルエラー等でデバッグできないのはかなり辛いです。そんなわたくしの悩みを解決してくれそうな第11章。しっかりスクリプトデバッグ方法を学習したいと思います。

shコマンドでのスクリプト実行

スクリプトを実行する方法は2つ。

  • コマンドのようにスクリプトを実行する
  • shコマンドを使用して実行する
    • shコマンドの後に、スクリプトファイルを指定し、そのあとにパラメータを指定する
    • スクリプトファイルには実行権限は必要ない。
    • デバッグオプションが使用できる。

shコマンドのデバッグオプション

  • vオプション
    • シェルスクリプトが実行しようとしていることを1つ1つ表示してくれる。
    • ただし、ループの内容を1回1回表示することはない。
    • 入っている変数の内容も表示されない。
  • xオプション
    • シェルスクリプトが実際に行ったことを表示してくれる。
    • 変数の内容も表示される。
    • 実際に実行したコマンドの先頭には+マークが付く。

上記の両方を同時に使用すれば、だいたいそのシェルスクリプトの処理内容を把握できる。

スクリプト中にvオプション等を埋め込む

スクリプトの中にvオプション等を使用したいときは、スクリプト内で

set -v

と記載するだけ。
もし、有効にしたけど無効にしたいときは

set +v

と記載すればいい。

nオプション

nオプションを使用すると、シェルスクリプトの構文や整合性をチェックするだけで、実際には実行しない。

書き方の注意事項

基本的な話しかもしれませんが、間違えやすい事をまとめてくれているので、しっかり見ていきたいと思います。

変数への代入

変数への代入は、イコール(=)の前後には空白はNG。もし、スペース等を代入するときはクォーテーションで囲う必要がある。

中括弧({})

コマンドをグルーピングするときは、最後のセミコロン(;)を忘れないように

{ コマンド1; コマンド2; ....;}
鉤括弧([])

「〜でない」を意味するビックリマーク(!)をつける場合には、必ず最初の括弧([)の後に持ってくる。途中にビックリマーク(!)を持ってくると文字列として扱われる。

case文

1つの文の最後を示すセミコロン2つ(;;)を忘れないようにする。セミコロンの間にスペースを入れてはいけない。

複数行にまたぐとき

1行を2行で記述するとき、バックスラッシュ(\)を記載するが、バックスラッシュの後にコメント等を記載するとエラーになるので注意。

testコマンド

testコマンドを括弧([])で記載するときは、括弧のの手前も下記のようにスペースを入れる必要がある。

if [<space>"$NAME" = ""<space>]; then

testコマンドで比較するとき、文字列であればイコール(=)、数字であればeqで比較する。

exprコマンド

exprコマンドも式や値の間にはスペースが必要。exprコマンドを使って変数に格納されているのが数値かどうかを判断できる。下記にサンプルを示す。

if expr "$NUMBER" + 1 > /dev/null 2>&1
if [ $? -lt 2 ]; then
    echo "Numeric"
else
    echo "Not numeric"
fi
readコマンドでファイルを読み込む

readコマンドでファイルの先頭3行を読み込む時には下記のようにする。

exec 3< ファイル
read LINE <&3
read LINE <&3
read LINE <&3

読み込ませるのであれば、下記の方法でもいい。しかし、下記の例で注意しないといけないのは、下記の方法だと、whileがサブシェルで動作するのでwhile内の変数はwhile外では使用できないこと。

while read LINE
do 
    ...
    ...
done < ファイル

もし、while外でもwhile内の変数を利用したければ、下記のようにexecコマンドにリダイレクトしカレントシェルとして動作させる。

exec < ファイル
while read LINE
do 
    ...
    ...
done

***UNIXのファイル名
UNIXのファイル名には、スラッシュ(/)ヌル(\000)以外なら何でもOK

***カラの変数
変数がカラの場合もあるときにはクォーティングを忘れないように。下記の場合、変数がカラだとエラーになってしまう。
>|sh|
NAME=
if [ $NAME = "" ]; then
   echo "NAME is empty."
fi

そこで下記のように$NAME変数をクォーティングする。

NAME=
if [ "$NAME" = "" ]; then
   echo "NAME is empty."
fi
リダイレクション

ファイルにリダイレクトするときは、スペースがあってもなくてもいい。

echo a b c >tmp
echo a b c > tmp

しかし、ディスプリタとかの場合にはスペースなしでないとまずいので、その場合とそろえる意味もあって、上記のスペースなしの方がいい。

終わりに

この第11章は、デバッグの手順と書いてありましたが、基本的にはスクリプトを書くときの注意事項って感じでした。shコマンドでデバッグができますが、あまり突っ込んだことや、サンプルは少ないので、それはこれから自分が使って慣れていくしかなさそうです。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第9章:シェル関数の例

始めに

第9章では、実用的なシェル関数を実際に作りながら、シェル関数をどうやって作ればいいかを学習。サンプルもたくさんあるし、今までの文法のおさらいにもなるので、時間を掛けてゆっくりやっていこうとおもいまする。
全体で35ページほどあるので、ぼちぼちやりごたえはありそうでございます。

シェル関数とは

シェル関数は、他のシェルスクリプトから呼び出され、目的にあった応答を返すように作られたもの。通常、拡張子は.shとし、シェル関数のファイルは直接実行するわけではないので、実行権限は必要なく読み取りだけでもいい。
動作確認とかをしたければ、当然、シェル関数を呼び出さないといけいので、呼び出すシェルスクリプトも作成しなければならない。

復習

  • $#
    • 引数の数が入る
  • $?
    • コマンド終了時の終了ステータスが入る
    • 正常終了なばら0
  • .コマンドでの読み込み
    • 現在のシェルと同じプロセスで動かす
  • マイナス(-)での変数代入(p47)
    • 値を代入しないが、そのときだけその値を返す
    • 左辺で指定した位置パラメータに値が入っていないときだけ、その値を返す。
  • OR(||)
    • 左からコマンドを試していき、コマンドが成功したらそれ以上先のコマンドを実行しない。
  • 中括弧({})によるグルーピング
    • { コマンド1 コマンド2}と1行で記載した場合にh、最後のコマンドには;が必要だが、複数行に分けたときには;は必要ない。
    • コマンドがカレントシェルで実行されるが、リダイレクトしたときはサブシェルで実行される。
  • $@
    • 引数全体を示す変数
    • ダブルクォートで括られると、それぞれの引数を1つずつダブルクォートに囲んで展開する。
    • 引数がダブルクォートで括られている場合などに使用する。(p51)

CheckHostname関数

リモートホストpingで生存チェックするための関数。
最終的にコマンドを処理して値を返す関数の場合、コマンドの結果を見て返す値を変えていくよりは、コマンド自体の結果を直接返したほうが楽になる。そのとき、コマンドのメッセージを/dev/nullに入れることを忘れないように。

Clear関数

端末画面をクリアする関数。
コマンドがない場合の処理を学習するための関数。

stty -a

現在使用中のterminalの行数、幅数などが確認できる。以下にサンプルを示す。rowsが行数(サンプルだと24)、columnsが幅数(サンプルだと80)

speed 9600 baud; 24 rows; 80 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
	-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
	-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
	-ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
	-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
	eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
	min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
	stop = ^S; susp = ^Z; time = 0; werase = ^W;

DownShift関数

アルファベットの大文字を小文字にする関数
引数の取得方法を学習するための関数

FullName関数

ファイルやディレクトリの完全パス名を表示する関数

  • testコマンドの復習
    • testコマンドの書式は2つ
      • test 比較
      • [ 比較 ]
    • dオプションは、ディレクトリであれば真を返す
    • fオプションは、ファイルであれば真を返す

GetYesNo関数

質問を出して、YesかNoの応答を取得する。

  • echoコマンドのnオプション
    • 改行コードを抑制するオプション

IsNewer関数

  • ファイルのタイムスタンプの復習
    • タイムスタンプは3つ
      • アクセスした時刻
      • ステータスの変更時刻(モードやユーザなどを変更した場合)
      • 修正時刻

このスクリプトは、ファイル内容に変更が加わった修正時刻の比較を行う。

  • testコマンドの復習
    • oオプションはORでのグルーピング
    • nオプションは文字列の長さが0より長ければ真を返す

InNumeric関数

文字列が数値かどうかを判定する関数
exprの終了ステータスとかを使った判定方法を学習

  • exprコマンドの復習
    • 結果が0の数値になるときの終了ステータスは1
    • 結果が0以外の数値になるときの終了ステータスは0
    • 計算できなかったときの終了ステータスは2

IsSystemType関数

システムのタイプが正しいかを判定
特になし。

Prompt関数

応答要求メッセージを出力する関数
特になし。

Question.sh

応答要求のスタイルを定型化した関数
特になし。

終わりに

正直って、やってて一番辛い章でした。。。今まで勉強してきたことが出てきたので、いい復習になったのですが、なにぶん単なる関数ファイルなので実行して確認しようと思っても面倒だし、やっぱしプログラミングは実行してナンボですね。。。
次の第10章は、待ちに待った「シェルスクリプトの例」です。バンバン実行してたのしもーっと。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第8章:シェルのいろいろな機能

始めに

なんと第8章は約60ページもある。。。マラソンを走る前の気分です。。。まぁ、ぼちぼちやろうと思います。
肝心の内容ですが、文字列の扱いだったり、ファイルやディレクトリの扱いだったりと、UNIXらしい内容なので、文法や変数と違って楽しくできそうです。これで、やっと実際に使えそうなシェルスクリプトを書けそうです。

文字数の長さを調べる

exprコマンドを使う。exprコマンドは:(コロン)があると、右と左の文字列を比較して「先頭から何文字が等しいか」を返す。これを利用する。変数もこれで比較ができるが、変数に:や*が1文字だけ入っているとexprコマンドが演算子と判断するのでエラーになるので、別途対応する必要がある。

expr "hogehoge" : '.*'
8

終了コードにて文字列検索

$?には終了コードが格納されるので、ps -ax | grep hoge などのときに、hogeの文字列が見つかった場合は$?に0が格納され、見つからなかったときには1が格納される。サンプルを示す。

$ ps -ax | grep hoge
$ echo $?
1

exprを使った文字列の中の一部切り出し

exprコマンドは、:(コロン)の左の文字の中から右で指定された文字列の中で\(と\)の間の文字を切り出す。下記にサンプルを記載する。

$ expr "abcdefghijklmn" : "a.*\(e..h\)i.*"
efgh

exprとsedで最初の2文字を切り出す

sedの場合
STRING=`echo "$STRING" | sed -e 's/^..//'`
exprの場合
STRING=`expr "$STRING" : "..\(.*\)"`

setコマンドでの切り出し

setコマンドの引数を--とすると、その後の文字列を位置パラメータの1番目から順番に格納する。引数の数は変数$#に入る。これを利用して文字をIFSで切り出す事が可能。以下にサンプルを示す。

$ set -- `date`
$ while [ $# -gt 0 ]
> do
>       echo $1
>       shift
> done
Wed
Mar
24
21:42:52
JST
2010

cutコマンドでの切り出し

cutコマンドでも、区切り文字を指定して切り出すことが可能。下記の例では、区切り文字を「:」とし、2番目のフィールドを切り出すようにしている。

$ echo "abc:def:ghi" | cut -d':' -f2
def

echoで改行させない方法

echoコマンドで文字を出力した場合、echoコマンドは改行コードも出力するため表示結果も改行されてしまうが、-nオプションを使用することで改行させないことができる。ただし、これはBSD系だけで、System V系の場合はメッセージの最後に\cと言うコードをつける。このようなOSの種類によって使い方が異なる場合、チェックするシェルスクリプトを記載するか、シェル関数を使って判断させる。OSを判断するシェル関数は9章で。

$ echo -n "message ..... "
message ..... $

yesかnoかの入力の判定

スクリプトでYesかNoの判断するのは大変なので、シェル関数「GetYesNo」を使うことで判断できる。GetYesNo関数は第9章で。

画面のエコーバック

デフォルトでエコーバックされて、ユーザが何を入力したかわかるようになっている。エコーバックを無効にするには下記のコマンドを入力する。

$ stty -echo

この機能を使ってシェルスクリプトで入力されるパスワードを表示しないようにできる。

stty -echo
echo "Enter your password."
read PASSWORD
stty echo

basenameコマンド

引数で渡されたディレクトリやパスの最後の/以降のものを表示する。実際にそのファイルやディレクトリがあるかは確認しない。以下にサンプルを表示する。

$ basename /etc/hosts
hosts

dirnameコマンド

basenameコマンドと逆で、引数で渡されたパラメータの最後の/以降を切り落としたものを表示する。以下にサンプルを表示する。

$ dirname /etc/hoge/go/keiji/
/etc/hoge/go

findコマンド

findでファイルやディレクトリのリストを確認できる。findコマンドのパラメータを見ていく。

find . -print

カレントディレクトリ内のファイルやディレクトリのリストを表示する。

find `pwd` -print

カレントディレクトリ内のファイルやディレクトリのリストを完全パスで表示する。

find -type

typeオプションで表示するファイルの種類を絞ることができる。例えば、ディレクトリだけ表示させたいときは下記のようにtype d と指定する。

find . -type d -print
find -name

nameオプションは、指定された文字列とマッチするものだけを表示する。例えば、/usrの中にあるaで始まり.hで終わるファイルを表示させたい場合の例を示す。

$ find /usr -name "a*.h" print

また、!を使用することで否定する文字列を探すことも可能。以下にカレントディレクトリ内で拡張子がJPEGとtmp以外のファイルを表示するサンプルを示す。

$ find . -type f ! -name "*.jpeg" ! -name tmp -print

cpコマンドでのディレクトリのコピー

ファイルをコピーするにはcpコマンドでコピーする。もしディレクトリも丸ごとコピーしたければ-rオプションをつけてコピーする。

tarコマンドのでのディレクトリコピー

tarコマンドでディレクトリをコピーすると、コピー元のファイルやディレクトリの所有権やアクセス権や日付をそのまま残してコピーすることが可能。下記にtarコマンドでのコピーの例を示す。tarコマンドでファイル名に-を使うと、標準出力に書き出したり読み出したりすることができる。

(cd ソースディレクトリ; tar -cf - .) | (cd ディスティネーションディレクトリ; tar -xf -)

ファイルの日付による操作

lsコマンドでの日付比較

lsコマンドは-tオプションをつけると、ファイルの最終修正時刻の新しいもの順に並べる。さらにsedで先頭のファイルを抜き出せば、それが新しい方のファイルとなる。下記にサンプルを表示。

ls -t ファイル1 ファイル2 | sed -n '1p'
findコマンドでの日付比較

findコマンドの-newerオプションを使うと、最初の引数に指定されたファイルが新しければ、最初のファイルを表示し、2番目のファイルの方が新しい場合には何も表示しない。下記にサンプルを表示。

find ファイル1 -newer ファイル2 -print
ある時間より新しいファイルの検索

時間を指定してtouchコマンドでファイルを作成し、findコマンド等でそのファイルと比較させる。下記にtouchコマンドで2010年3月20日12時35分52秒のファイルを作成し、findコマンドで比較する例を表示。

$ touch -t 1003201235.52 test
$ find . -newer test -print

終わりに

この章に掲載されているコマンドやシェルスクリプトを1つ1つ試していくと、結構時間がかかりますが、この章では一般的なUNIXのコマンドの紹介も結構あったので、UNIXのコマンドを知っている方はさらっと読める章だと思います。あと、この章で紹介されているシェルスクリプトは、第2章あたりで紹介されていることも結構あるので、ちょうど良い復習になったりもしまする。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第7章:フィルタの使用法

始めに

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界」の第7章は、「フィルタの使用法」となっていますが、ようはsedです。いや、やっとsedですよ、sed。男子たるモノ、sedくらい使えないとどないする?って感じのsedです。もちろん、女子でsedを使えるとかっこいいなぁ。
ってわけで、sedは楽しみなの第7章は楽しくできそうです。ページは25ページほどなのでそんなに大変ではなさそう。

フィルタとは

フィルタとは、標準入力からデータを受け取って、変更を加えて標準出力に書き出す処理のこと。通常は下記にようにパイプ(|)を使って行う。パイプを使えば複数のフィルタも簡単にできる。

cat	file	|
	filter	|
	filter2	|
	while read LINE
	do
		・・・
	done

もし、複数のファイルをいっぺんにフィルタしたければ、並べて書いてパイプで渡す。

cat file1 file2 file3    | filter

下記のようにリダイレクトを使ってもフィルタが可能。

filter1 < file | filter2

sedコマンド

sedコマンドは、標準入力からデータを受け取って、編集後の結果を標準出力に書き出す。この章ではsedを使ってフィルタを練習する。

sedの基本

e、sオプション

sedの-eオプションは、後ろの/に続く文字列が編集用のコマンドと言うことを示す。sは、substitute(置換)の意味で、/の左側の文字列を/の右側の文字列に置き換えると言う意味になる。下記の例だと、ファイルの中の「OldText」と言う文字列を「NewText」と言う文字列に置き換えるとなる。

$ sed -e "s/OldText/NewText/" ファイル
gオプション

上記の例だと、1行に2つ以上の「OldText」と言う文字列があった場合、最初の「OldText」しか置換しない。もし、1行で複数の置換を行いたい場合は最後の/の後にg(global)をつける。

$ sed -e "s/OldText/NewText/g" ファイル
変数を使用した編集

変数を使用した処理も可能。

$ OLDTEXT=OldText
$ NEWTEXT=NewText
$ sed -e "s/$OLDTEXT/$NEWTEXT/" ファイル

-n,pオプション
sedは、デフォルトで処理した行も処理しなかった行の両方を出力する。もし、処理した行を出力したい場合は-nオプションを使用する。注意事項として、-nを使用した場合、「出力しなさい」と言う意味の-pオプションも必ず一緒に使用しなければならない。-nの意味は、本当は指定した行だけを出力しないさという意味になる。なので、下記の例だと2行目だけ出力するという意味になる。(編集してなくても)

$ sed -n '2p' < ファイル

編集した行だけ出力させたければ下記のようにする。

sed -n -e "s/OldText/NewText/gp" ファイル

パイプを使ったsedの処理

リダイレクト等で処理を行うと、何度もsedで編集する場合、中間ファイルができてしまう。そこで中間ファイルを作りたくない場合はパイプを利用する。例としては以下の通り。下記のようにパイプで渡していけば、何回でも編集が可能になる。

sed -e "s/Old_1/New_1/g" | sed -e "s/Old_2/New_2/g" | 

デリミタ(/)の変更

文字列を区切ってる/をデリミタと呼ぶ。もし、/をしたい場合は\等でエスケープしてもいいが、それだと可視性がよくないのであまり推奨されない。そこで、デリミタに/を使用するが、本当は何でもいいので、%や@をデリミタに使用することもある。

文字の変換

置換はsを使用する。g(global)がない場合は行の最初にマッチしたものだけ置換する。

sed -e "s/置換前/置換後/g"

文字の削除

sedを使って文字の削除も可能。置換の機能を利用して、何もない文字に変換すると言うやり方。

sed -e "s/置換前//g"

行の先頭の文字列を消す

指定した文字列が行の先頭にあったときだけ、その文字を削除する。^が「行の最初」を表す。

sed -e "s/^置換前//"

行末の文字を消す

今度は行の最後に指定した文字があれば、その文字を削除する。$が「行の最後」を表す。注意事項として$はシェルの特殊文字なので、sedより先にシェルに解釈させるとまずいので\をつけてエスケープさせる必要がある。

sed -e "s/置換前\$//"

文字列の追加

文字の追加は、基本的には行の最初や行の最後しかできない。もし、文中に追加したい場合は下記のように置換の延長で行う。

sed -e "s/abc/abcxyz/g/"

行の先頭に文字を追加

^を使って行の先頭に文字を追加できる。

sed -e "s/^/追加したい文字列/"

行の最後の文字を追加

上記と同じ。単に$を使うだけ。$なので、エスケープも同じ。

sed -e "s/\S/追加したい文字列/"

ドット(.)とアスタリスク(*)

任意の文字列を削除や編集したいときにはドットやアスタリスクを使用する。

  • ドットは任意の1文字を示す。
    • 1文字であれば.
    • 4文字であれば....
  • アスタリスクは、直前の文字が任意の個数連続したことを示す(0回も含む)
    • aで始まる文字を表すときはa*(aだけも含む)

先頭の3文字を無条件で削除するときの例

sed -e "s/^...//"

.*とすると、すべてとなるので、すべての行をabcに置き換える例は書きの通り。

sed -e "s/.*/abc/"

スラッシュ(/)以外のデリミタ

例えば、abc/def/ghiの文字列で、最初の/以降の文字を切り落としたい場合、スラッシュ以外を使う。例としては%を使用。

sed -e "s%/.*%%"

sed以外での切り落とし

切り落とす文字数がわかってないときには.*を使わないといけないが、もし何文字目を切り落とすかわかっているのであれば、cutコマンドやawkコマンドを使用する。例としてcutコマンドにて最初(1文字目)から5文字目までを切り落とすサンプルを表示する。awkはまたいつか。。。

echo "$STRING" | cut -c1-5

大文字小文字の入れ替え

大文字と小文字の変換にはtrコマンドを使用する。以下に指定したファイルの大文字を小文字に変更するサンプルを記載する。

$ cat ファイル  | tr '[A-Z]' '[a-z] > 変更後のデータ格納ファイル

タブをスペースに変換

単にタブとスペースを指定すればいいだけ。

sed -e "s/<tab>/<space>/g"

複数のスペースを1つのスペースにマージ

複数のスペースを指定するには*で表現できるので、あとは同じ。気をつけないといけないのは、*で指定するとスペースなしも含まれてしまうので、*としてスペースを2つ指定するべし。以下にサンプルを記載。

sed -e 's/<space><space>*/<space>/g'

ホワイトスペースを1つのスペースへ変換

始めて聞きましたが、ホワイトスペースとはタブかスペースのことを言うそうです。ようするにタブとスペースの混在ですな。そんな混在しているものを1つのスペースに統一するときのやり方を下に記載。[]を使うことで、どちらかと言う表現が可能なので、下の例だとなどがマッチする。

sed -e 's/[<space><tab>][<space><tab>]*/<space>/g'

先頭のホワイトスペースを削除

シングルクォートの場合

sed -e 's/[<space><tab>]*$//'

もしダブルクォートを使用する場合は、$をエスケープする必要がある

sed -e "s/[<space><tab>]*\$//"

指定した文字列を含んだ行を削除

削除の場合、先頭のsが不要になる(sは変換するときに必要なだけ)。最後のdが削除を示す。

sed -e "/文字列/d"

同じことをgrepコマンドでも可能。grepコマンドで-vオプションを使用すると「該当する文字列を含んだ行は表示しない」となる。

grep -v "文字列"

空白行の削除

下記の例は、改行コードのみの行を削除。もしスペースやタブだけの行を削除したければ、さらに下のサンプルを参照

sed -e '/^$/d'

タブやスペースだけの行も削除

sed -e '/^[<space><tab>]*$/d]'

sedによる行の指定

sedは、対象とする行を指定することも可能。以下に5行目から10行目のみ処理を当てたいときのサンプルを記載する。

sed -e "5,10s/置換前/置換後/g" ファイル

もし、指定した行から最後までとかを指定したい場合には$を使用する。$は最終行を表す。下記は5行目から最終行までのサンプル。もし、ダブルクォートでくくる場合は$のクォートを忘れないように。

sed -e '5,$s/置換前/置換後/g' ファイル

行の削除

先ほどの方法を使って行の削除も可能。1行目から4行目の削除のサンプル。

sed -e '1,4d' ファイル

最後の4行を削除するサンプル

sed -e '$-3,$d' ファイル

指定した行だけの表示

nオプションをつければ可能(nオプションは処理した行だけ表示するという意味)。nオプションを使用するときはpオプションも忘れずに。1行目だけを表示するサンプル。

sed -n '1p' ファイル

もしn行目からm行目までの場合は以下の通り。

sed -n 'n,mp' ファイル

キーワードによる行の指定

sedで処理するときに対象を行で指定することもできるが、キーワードで指定することも可能。例えば、下記の例だとBeginと言う文字列からEndと言う文字列の間っていう指定を行う。

sed -e "/Begin/,/End/d" ファイル

もし、指定するキーワードのみの行となっているのであれば、下記の例がいいそうだ。

sed -n "/^Begin\$/,/^End\$/p" ファイル

ファイルを後ろから表示

grepの-nオプションを使って先頭に番号をつけ、sortコマンドで並び替える。最後にsedで行番号を削る。以下にサンプルを掲載。

$ cat ファイル | grep -n '.*' | sort -n -r | sed 's/^[0-9]*://'

終わりに

1つ1つ確認していったので、思いのほか時間がかかりましたが、しっかり理解するには実際に1つ1つ試していくのがいいかと思いまする。あとは、実際に使おうと思ったときに思いつくかどうかっすね。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

第6章:コマンド行の解析、処理

始めに

第6章はコマンドラインの処理とからしい。渋い。この章はページが15ページほどなので、気軽に読めそう。10章のサンプルスクリプトまで、あともーすこし。週末までには何とかたどりつきたなぁ。

コマンドラインの復習

コマンドラインは、最初にコマンドがきて、その後に引数がくる。引数と引数の間に空白があると別の引数として認識されるため、もし1つの引数で間に空白がある場合は下記のようにクォーティングしておく。

command "Hello World"

バックスラッシュで改行をエスケープできるので、下記のように1つのコマンドを複数行に分けて書くことができる。

echo "part one;" \
          "part two."

上記のコマンドと下記のコマンドは同じ

echo "part one;" "part two."

シェルスクリプトでのオプション処理

シェルでオプションを解析したりするにはgetoptsコマンドを使用する。getoptsコマンドの書式は以下の通り。

getopts fv: OPT

シェルスクリプトで使用できるオプションに引数が必須の場合には「:」をつける。上記の例だとvオプションの場合には引数が必須となる。もし、vとxが引数が必須の場合には下記の例となる。

getopts abv:x: OPT

処理を行うときは変数OPTにオプション(fやv)が入り、スクリプトはそれを1つ1つ処理していく。引数に関してはgetoptsが用意した$OPTARGに格納される。変数OPTINDもgetoptsの用意している変数で、OPTINDには最後のパラメータの位置パラメータが格納されてる。

getoptsがないとき

getoptsがないときには、getoptが使用される。getoptsはgetoptの拡張版なので、そんな違いはなさそう。もし出くわしたときにはP148を見ればgetoptコマンドの解説が載っているので、それでも見よう。

その他のオプション処理方法

引数処理では、引数の数が重要になる場合、$#が引数の数を持っている変数なので、この変数を利用し引数の数をチェックする。
もし、個数の定まらない引数の場合には下記のように引数チェックを行う。

while [ $# -gt 0 ]
do
        FILE=$1
        shift
        ・・・
        ・・・
done

for文で同じことを行うなら

for FILE
do
        ・・・
        ・・・
done

上記のように変数に値を与えるリストを書かなかった場合、変数(上記の例だとFILE)に位置パラメータが順に格納されていく。しかし、引数に空白などが含まれている場合などはfor FILE in "$0"と正確にやった方がいい。

ifの条件式

そろそろ、if文の条件式が=(イコール)以外のものが当たり前のように出てくるようになってきました。今後のためにも下記にまとめておきます。

  • A = B AとBが等しい場合、真を返す
  • A -eq B AとBが等しい場合、真を返す(=と同じ)
  • A -ne B AとBが異なる場合、真を返す
  • A -gt B AがBより大きい場合、真を返す
  • A -ge B AがB以上大きい場合、真を返す
  • A -lt B AがBより小さい場合、真を返す
  • A -le B AがB以下小さい場合、真を返す

終わりに

この第6章自体は短かったのだが、getoptsコマンドのshiftがなかなか理解できなくて結構時間がかかりました。理解できるまでshiftしまくりでした。。。あとはそんなに難しくなかったように思います。やっと「入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界」が半分終了でございます。まだまだ書き方の解説のページが続きそうですが、地道にがんばりたいと思います。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界