詳説 正規表現 Part2
Rubyの簡単なサンプル
if ($reply =~ m/^[0-9]+$/)
=~ の部分は マッチする と読むと便利。
m は正規表現マッチを試みるという意味。
$celsius =~ m/([-+]?[0-9]+)([CF])$/
括弧で囲むことによって、$1には [-+]?[0-9]+ にマッチしたテキスト、$2には [CF] にマッチしたテキストがセットされる。
$input = <STDIN>;
ユーザが入力した1行を読み込む。
chomp($input);
$inputの末尾の改行文字を取り除く。
$input =~ m/^([-+]?[0-9]+(\.[0-9]*)?)([CF])$/
小数も入力できるようにしたもの。
小数部分の (\.[0-9]*)? は?のための括弧だが、これも変数にキャプチャされる。
つまり $1 には [-+]?[0-9]+(\.[0-9]*)?)
$2 には (\.[0-9]*)
$3 には ([CF]) にマッチしたテキストがセットされる。
[<space><tab>]*
スペースとタブの混合に対応できる。
<tab>の代わりに、見た目的にわかりやすい\t というメタ文字が用意されている。
他にも \n 改行や、 \f ASCIIの改ページ、 \b バックスラッシュ がある。
\s*
\s は空白文字にマッチする文字クラス全体の略記法である。
空白文字には、スペース、タブ、改行、復帰が含まれる。
これで空白文字全般にマッチできる。
m/^[CF]$/i
/i記法はPerlの修飾子の指定方法の1つである。
/iは正規表現の後ろに置くと、大文字と小文字の区別をしないようにPerlに指示する。
\t タブ文字
\n 改行文字
\r 復帰文字
\s 任意の空白文字
\S \s以外のすべての文字
\w [a-zA-Z0-9_]
\W \w以外のすべての文字
\d [0-9]
\D \d以外のすべての文字
詳説 正規表現 Part1
メタ文字について
^cat
行頭のcatという文字にマッチする。
cat$
行末のcatという文字にマッチする。
gr[ea]y
greyかgrayという文字にマッチする。
[0-9a-zA-Z]
数字、英字の大文字、小文字のどれかにマッチする。
[ ] の中にある !.? などはメタ文字ではない。
q[^u]
qの後にu以外の文字が続く文字列にマッチする。
[^・・・] 否定文字クラスは リストに含まれていない文字にマッチする。
03.19.76
. は任意の1文字にマッチするので、03/19/76などはマッチする。
Bob | Robert
Bob か Robert という文字列にマッチする。
このように結合された部分正規表現は選択肢と呼ばれる。
\<cat\>
catという単語にマッチする。
\< や \> はメタ文字列といい、単語の先頭と末尾という位置にマッチする。
colou?r
color か colour という文字列にマッチする。
? は量指定子で、必要最小数が0、マッチ試行の上限は1である。
a*
a や aa や aaa という文字列にマッチする。a がなくても構わない。
* は量指定子で、必要最小数が0、マッチ試行の上限は無制限である。
a+
a や aa や aaa という文字列にマッチする。a は最低限1つは必要。
+ は量指定子で、必要最小数が1、マッチ試行の上限は無制限である。
[a-zA-z]{1,5}
英字の大文字、小文字が最低1文字あればよし、最大5文字までマッチする。
{min,max} というメタ文字列は範囲指定繰り返し制御と呼ばれる。
([a-z])([0-9])\1\2
\1 は [a-z] がマッチしたテキスト、 \2 は [0-9] がマッチしたテキストを参照する。
\1 や \2 を後方参照という。
[a-zA-z_][a-zA-Z_0-9]*
先頭文字として英字の大文字、小文字とアンダーバーが認められ、2文字目以降としては、それに加えて数字も認められる識別子のような文字列にマッチする。
"[^"]*"
ダブルクォーテーションで囲まれた文字列にマッチする。
UNIXシェルスクリプト第3章Part1
シェル関数、組み込みコマンド
name()
{
command
}
関数の定義の仕方。
return [n]
関数の戻り値の設定の仕方。
任意の番号を設定すれば、それがこの関数の戻り値となる。
ここで返す値は通常のコマンドの実行終了ステータスと同じ取り扱いになり、シェル変数の$?で参照可能。
動作状態により違いに関する注意
●ディレクトリ
関数内でディレクトリを移動する操作を行った時、カレントシェルで実行している場合には、関数の終了時にディレクトリはそれにつられて移動している。
一方サブシェル内で実行している場合には、関数の終了後、元のディレクトリに戻る。
●変数
関数内で何か変数に対して処理を行った時、カレントシェルの場合にはその変更内容が残る。サブシェルの場合には関数が終了すれば元の値に戻る。
●exitコマンド
関数内でexitコマンドを実行した時、カレントシェルで実行してい関数の場合には、関数はもちろんそのシェル自体が終了する。サブシェルで実行している場合には、その関数が終了するだけ。
シェル関数内の位置パラメタ($*)
シェル関数では$0は関数の名前にならず、関数を読んだ元のシェル(あるいはシェルスクリプト)の名前になる。
何らかのシェルスクリプトの中でこの関数を実行すると、$0はそのシェルスクリプトの名称になる。
$ . script_file
ドットというシェルの組み込み関数を使用してシェルスクリプトを実行させると、中に含まれているコマンドは、現在のシェル上で動作することになる。
つまりドットコマンドを使うことで、シェルスクリプト内で定義された関数を現在のシェルから利用できるようになる。
環境設定をするシェルスクリプトは、ただ実行しても効果がないため名前の最後に.shを付け、ドットコマンドを使って実行するシェルスクリプトであることを明示することが多い。さらに直接実行しないように、モードは読み書きだけを許可し、ディレクトリも普通のコマンドとは分けておくようにする。
UNIXシェルスクリプト第2章
シェル変数の初期設定
${variable:=value}
${variable=value}
値がある場合、そのままの値を利用する。
値がない場合、valueの値を代入する。
コロンがある場合は変数が未使用、もしくはヌル値がセットされているときに値がないとみなす。
コロンがなければ、変数が未使用の場合のみを値がないとみなす。
${variable:-value}
${variable-value}
値がある場合、そのままの値を利用する。
値がない場合、代入はせず、valueの値を利用する。
${variable:?message}
${variable?message}
値がある場合、そのままの値を代入する。
値がない場合、messageの部分が表示される。
message部分を省略すると、デフォルトのメッセージが表示される。
${variable:+value}
${variable+value}
値がある場合、代入はせず、valueの値を利用する。
値がない場合、何もしない。
$* と $@ の違い
$* $1 $2 $3 ...
$@ $1 $2 $3 ...
"$*" "$1 $2 $3 ..."
"$@" "$1" "$2" "$3" ...
基本は同じで、ダブルクォーテーションで囲まれたときの挙動が異なる。
$* では1つの文字列になる。$@ではそれぞれ別の文字列になる。
また、位置パラメタになんの値もセットせれていない場合、
"$*"ではヌルに、"$@"では""に置き換わる。
ヌルの場合はパラメタとして処理しないが、""は「何もないパラメタがある」と処理される。
$?変数
コマンド実行時の終了ステータスを表す。
$$変数
現在動作しているコマンドの「プロセスID」がセットされる。
$!変数
&を使ってコマンドをバックグラウンドで走らせたとすると、そのコマンドのプロセスIDがセットされる。
wait $! でバックグラウンド処理が終了するのを待つことができる。
$-変数
そのシェルの起動時のフラグや、setコマンドを使って設定したフラグの一覧がセットされる。
$ CFLAGS=-g make
このようにmakeコマンドを実行すると、CFLAGSという変数に-gという値がセットされ、その変数にこの値を設定した状態でmakeコマンドが実行される。
あくまでその直後のコマンドのための設定であり、他にこの変数や値を利用することはできない。
第02章終了。
UNIXシェルスクリプト第7章 Part2
sedを使っての編集
sed -e "s/^TextToRemove//"
^ は行の先頭を表す。^abcという指定にすれば、行の先頭にabcという文字列がある場合、という意味になる。
先頭のみを指すので、gは付ける必要がない。
sed -e "s/TextToRemove\$//"
$は行の末尾を表す。$はシェルの特殊文字なので、\ をつけてエスケープさせる。
sed -e "s/^/TextToInsert/"
行の先頭をTextToInsertで置き換えるという感じ。
これで行の先頭に文字列を追加できる。
sed -e "s/\$/TextToAppend/"
行の末尾をTextToAppendで置き換えるという感じ。
これで行の末尾に文字列を追加できる。
sed -e "s/^...//"
. は任意の1文字を表す。つまり ^... は先頭の3文字を表す。
sed -e "s/a*//"
* は直前の文字が任意の個数連続した場合を表す。
つまり a* はヌル、a、aa、aaa、...を表す。
よってどんな文字であれ、 .* で表現できる。
sed -e "s/Pattern1.*Pattern2//"
Pattern1から始まってPattern2で終わる文字列を消去する。
応用で様々なパターンがある。
s/e.....// eから6文字を消去
s/.*s// sという文字までを消去
s/(.*)/()/ 括弧の中の文字列を消去
USER=`id | sed 's/uid=.*(\(.*\)) gid=.*/\1/'`
\( と\) で囲んだ部分は \1 や \2 で指定できる。
つまり括弧で括った部分だけを取り出すことができる。
echo "$STRING" | cut -c1-5
cutコマンドは指定された部分を切り取る。
-c1-5は文字目から5文字目までを切り取る。
awk '{printf "%-.5s\n", $0}' < file
行頭から5文字だけを取り出す。
$ cat file | tr '[A-Z]' '[a-z]' > lowerfile
大文字を小文字に変換する。
$ sed -e 's/<space><space>*/<space>/g'
複数のスペースを1個のスペースに変換する。
<space>* とすると全部の文字の前にスペースが挿入されてしまう。
$ sed -e 's/[<space><tab>][<space><tab>]*/<space>/g'
ホワイトスペースを1個のスペースに変換する。
$ sed -e "/Text/d"
Textという文字列を含んだ行を削除する。
置換ではないのでsはいらない。最後にdeleteを意味するdを指定する。
grepコマンドを使うと
$ grep -v "Text" と同じ。
$ sed -e '/^$/d'
空白行を削除する。
スペースやタブも含めた削除をしたい場合は
$ sed -e '/^[<space><tab>]*$/d'
$ sed -e "5,20s/OldText/NewText/g" file
この場合5から20行目を処理する。
最後がわからない場合は5,$とすれば大丈夫。
$ sed -e '1d' file
ファイルの1行目を削除する。
$ sed -e '1,4d' file
ファイルの最初の4行を削除する。
$ sed -e '$d' file
ファイルの最終行を削除する。
$ sed -e '$-3,$d' file
ファイルの最後の4行を削除する。
$-3は最後から数えて3行目。
$ sed -n '1p' file
1行目だけを表示する。
-nオプションは指定した行を表示する。
$ sed -n '1,np' file
1行目からn行目までを表示する。
この書き方に限っては特殊な手法がある。
$ sed -e 'nq' file
こうすればn行目まで表示し、sedが終了(quitのq)する。
$ sed -e '/Begin/,/End/d' file
Beginを含む行からEndを含む行までを削除する。
$ sed -n '/Begin/,End/p' file
Beginを含む行からEndを含む行までを表示する。
$ grep -n '.*' | sort -n -r | sed 's/^[0-9]*://'
grepコマンドに-nオプションを用いて各行に行番号を付ける。
grepコマンドは標準入力からファイルを読み、指定したパターンに一致する文字列を含む行を出力する。その際、sedと同じ .* という表現ですべての文字列を指定する。
出力は以下のようになる。
1:line1
2:line2
3:line3
.....
これをsortコマンドで番号順に逆順に並べる。
-rオプションで逆順にソートできる。
最後にsedコマンドで行番号を消して表示すればファイルを後ろから表示できる。
第7章終了。
UNIXシェルスクリプト第7章 Part1
フィルタの使用法
cat file1 file2 file3... | filter_1 | ...
複数のファイルをまとめて処理したければ、catコマンドの引数にファイルを書き並べれば良い。
filter_1 < file | filter_2 | ...
1つだけのファイルならリダイレクション機能を使うほうが良い。
sedコマンドの使用法
$ sed -e "s/OldText/NewText/" samplefile
標準的な使い方。
$ sed -e "s/OldText/NewText/" samplefile > result
結果を残したければ、リダイレクトする。
$ sed -e "s/OldText/NewText/" < samplefile > result
$ cat samplefile | sed -e "s/OldText/NewText/" > result
どちらも上と同じ意味。
-eというオプションは、その後の文字列が編集用のコマンドだということを表す。
編集コマンドが1つしかない場合は省略してよい。
また、編集コマンド内のsは置換(substitute)を意味する。
s/OldText/NewText/g
1行の中で見つけた文字列をすべて置き換える場合には、globalを意味するgをつける。
$ sed -e "s/$OldText/$NewText/g" samplefile
変換処理をさせるコマンドの中には変数を使うことも可能。
ただし、ダブルクォーテーションで囲む必要がある。
$ sed -n '2p' < samplefile
-nオプションを使うと、指示した行だけを標準出力に書き出すという動作に変わる。
このオプションを使う場合は、printしなさいという意味でpを必ず一緒に使う。
$ sed -n -e "s/OldText/NewText/gp" samplefile
行指定と、置換処理を組み合わせると、このようになる。
pの位置に注意。
s%abc%ef%ABC-EF%g
sedコマンドのデミリタ(区切り文字)は慣習的に / を使うが、何を使っても良い。
宣言も特に必要なく、sの直後の1文字がデミリタとして扱われる。
処理させたい文字列に / が入っている場合などは他の文字をデミリタにするとわかりやすい。
UNIXシェルスクリプト第10章 Part10
ファイルをサーチするシェルスクリプト findfile
特に無し。
文字列をサーチするシェルスクリプト findstr
if [ "$OPTIND" = 1 ] ; then
getoptsが使える環境では、OPTINDという変数に自動的に1の値がセットされている。
while getopts iv OPT
getoptsコマンドは、コマンドのオプションを解析したりチェックしたりする。
getoptsの次に書かなくてはならない引数は、このシェルスクリプトで処理させようとするオプションを並べたものになる。
fv: なら指定することのできるオプションはfとvであり、vには何らかの値を付けなくてはならないという意味になる。
OPTというのはgetoptsコマンドが使用する変数。
xargs -e frep $I $L -- "$STRING /dev/null
xargsコマンドは標準入力から受け取ったデータをすべて次のコマンドの引数としてそのまま渡す。
第10章終了。