2. 所有者に対するパーミッションの状態 3. グループに対するパーミッションの状態
8.11 正規表現を使ったファイルの編集
正規表現を解釈できるコマンド は数多くありますが、ここでは、\sed", \awk" コマンド を 使ったファイルの編集方法について簡単に説明します。
8.11.1 sed
コマンド
\sed"とは\StreamEDitor"の略で、UNIXにおける最初のラインエディタである\ed"(ED itor)
コマンド が起源となっています。
通常、エディタコマンド による編集はファイルを対象としますが、\sed"コマンド は、ファイ ルのみならず、あるコマンド の実行結果を入力対象として編集作業を行ったり、標準入力(キー ボード からの入力)を対象として編集作業を行い、いずれの場合も結果を標準出力します(シェ ルの機能を使ってファイルに保存することもできます)。従って、編集対象となるファイルの 内容を直接書き換える事はできません。
ここで言う「編集作業」とは、「ある文字(列)を他の文字(列)に変更する」事を意味しま す。コマンド 形式は次のとおりです。
コマンド 形式
sophia% sed -e '実行したい命令' ファイル名
sophia% sed -f コマンド ファイル名 ファイル名
オプション 説明
-e コマンド 指定された\コマンド"を解釈し、編集を行う
-f ファイル名 指定した'ファイル名'に記述された命令を読み込み、
解釈し、実行する
-n 入力行の自動出力をしない
コマンド 形式の中で、\実行したい命令"とは、\ed"コマンド におけるファイル編集の際の コマンド を意味し、数多くのコマンド が用意されています(詳細はオンラインマニュアルを参 照してください)。
それではいくつかの使い方について簡単に説明します。ここでは、次のような内容のファイ ルがある事を前提にします。
sophia% cat le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd eee
ccc ddd eee eee
aaa ggg aaa iii
まず、\ggg"を\hhh"に変更するには、次のように入力します。
sophia% sed -e 's/ggg/hhh/' le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd eee
ccc ddd eee eee
aaa hhh aaa iii
実行結果は、変更対象の有無にかかわらず、全て標準出力として画面に出力されます。実行 結果を、変更対象となる行のみを出力したい場合は、\sed"コマンド のオプション\-n"とコマ ンド \p"使います。
sophia% sed -n -e 's/ggg/hhh/p' le 3 0
2 1
aaa hhh aaa iii
次に、1行目と4行目にある\aaa"という文字列を\AAA"に変更してみます
sophia% sed -e 's/aaa/AAA/' le 3 0
2 1
AAA bbb aaa ddd
bbb ccc ddd eee
ccc ddd eee eee
AAA ggg aaa iii
1行目、4行目とも、その行の先頭にある \aaa"は変更はされましたが、同じ行にある次の
\aaa" は変更されていません。これは、上記の命令方法では、「ファイルの内容を1行目から
順番に読み込み、その行で最初に見つけた文字(列)を別の文字(列)に変換したら、次の行の 処理に進む」という意味になってしまっているためです。すべての文字(列)も変更の対象に したい場合は、最後の \/"の後に\g"を指定します。
sophia% sed -e 's/aaa/AAA/g' le 3 0
2 1
AAA bbb AAA ddd
bbb ccc ddd eee
ccc ddd eee eee
AAA ggg AAA iii
これで全部変更できました。\g"は\G lobal"の略で、ファイル全体を対象とする事を意味 します。
今度は、3行目にある\eee"という文字列を大文字\EEE"に変更してみましょう。先の例の とおりに行うと次のようになります。
sophia% sed -e 's/eee/EEE/g' le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd EEE
ccc ddd EEE EEE
aaa ggg aaa iii
2行目の\eeeという文字列も\EEE"に変更されてしまいました。ある行だけを編集対象と したい場合、\s"コマンド の前に行を指定する事により実行できます。
sophia% sed -e '3s/eee/EEE/g' le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd eee
ccc ddd EEE EEE
aaa ggg aaa iii
行の指定においても範囲を指定できます。例えば、1行目と2行目にある\bbb"という文字
列を\BBB"に変更したい場合、次のように入力します。
sophia% sed -e '1,2s/bbb/BBB/g' le 3 0
2 1
aaa BBB aaa ddd
BBB ccc ddd eee
ccc ddd eee eee
aaa ggg aaa iii
このように、行の範囲の指定をする場合は、\s"コマンド の前に何行目から何行目かをカン マ(,)で区切って指定します。
今までの例は、実行結果を全て画面に表示していましたが、これらをファイルに保存するこ ともできます。
例1 シェルの出力リダ イレクション機能を使った場合。
sophia% sed -e 's/bbb/BBB/g' le > le1 3 0
2 1
sophia% cat le1 3 0
2 1
aaa BBB aaa ddd
BBB ccc ddd eee
例2 \sed"コマンド における\w"コマンド を使った場合。
sophia% sed -e 's/bbb/BBB/gwle2' le 3 0
2 1
aaa BBB aaa ddd
BBB ccc ddd eee
ccc ddd eee eee
aaa ggg aaa iii
sophia% cat le2 3 0
2 1
aaa BBB aaa ddd
BBB ccc ddd eee
sophia% sed -n -e 's/bbb/BBB/gw le3' le 3 0
2 1
sophia% cat le3 3 0
2 1
aaa BBB aaa ddd
BBB ccc ddd eee
例1は、シェルの機能を使った方法で、標準出力を\file1"というファイルに保存する場 合です。例2は、実行結果すべてをファイルに保存するのではなく、変更対象となった行のみ を\file2"および\file3" というファイルに保存する場合です。
\sed"コマンド は、変更したい文字列の部分に正規表現を使って変更作業を行う事ができま
す。例えば、行の先頭が\ccc"で始まる文字列のみ\CCC"に変更したい場合には、次のよう に入力します。
sophia% sed -e 's/
^
ccc/CCC/g' le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd eee
CCC ddd eee eee
aaa ggg aaa iii
このように正規表現を使う事によって、いろいろな編集が自分の思うままにできます。
今までの例では変更命令(シングルクォテーションで囲まれた部分)をコマンド ラインから 入力してきましたが、これらの命令(スクリプトと言う)をあるファイル(スクリプトファイル と言う)に書き込んでおき、実行時には、スクリプトファイルからスクリプトを読み込み、実 行することができます。
例えば、\sedfile"というスクリプトファイルに次のようなスクリプトを書いておいたとし
ます。
sophia% cat sedle 3 0
2 1
1,$s/eee/EEE/g
1,$s/^ccc/CCC/g
このスクリプトファイルを元にコマンド を実行するには、\sed"コマンド のオプション\-f"
を使います。
sophia% sed -f sedle le 3 0
2 1
aaa bbb aaa ddd
bbb ccc ddd EEE
CCC ddd EEE EEE
aaa ggg aaa iii
この様に実行したいスクリプトをファイルに格納しておき、\sed"コマンド の実行をファイ ルからという形にしておくと、同じスクリプトを必要なときに実行でき、作業効率が上がり ます。
この他にもいろいろな使い方ができますので、詳細についてはオンラインマニュアルを参照 するか、市販されている図書を参照してください。
8.11.2 awk
コマンド
\sed"コマンド と同様に、\awk"コマンド も入力の各行に対してスクリプトのセットを実行 します。
\awk"コマンド は、\sed"コマンド にある幾つかの制限を補ってくれます。コマンド の利用 形態は\sed"コマンド とよく似ています。
コマンド 形式
sophia% awk オプション 'fプログラムg' ファイル名
オプション 説明
-f ファイル名 \ファイル名"に記述された命令を読み込み、解釈し、
実行する
-Fc cの文字をフィールド セパレータとする(既定値はス ペース)
val=value プログラムで使われる変数valに変数値valueをセッ
トする
また、\awk"コマンド における変数として以下のものがあります。
変数名 説明
$数値 (数値)番目のフィールド を示す。ただし、$0 という指 定は特別で、行全体を示します。
それではいくつかの使い方について簡単に説明します。ここでは、次のような内容のファイ ルがある事を前提にします。
sophia% cat le 3 0
2 1
10 100 1000
1 5 7
はじめに、コマンド で \cat le"と実行した場合と同じ動作をさせるには次のように入力し ます。
sophia% awk 'fprintg' le 3 0
2 1
10 100 1000
1 5 7
次に、\print"の後に\$0"を指定してみます。
sophia% awk 'fprint $0g' le 3 0
2 1
10 100 1000
1 5 7
結果は同じです。それでは、\$0"の変わりに\$2"を指定してみます。
sophia% awk 'fprint $2g' le 3 0
2 1
100
5
今度は、各行の2番目の要素が取り出され、表示されました。それでは、この指定方法を 使って各行の全部の要素を取り出してみます。
sophia% awk 'fprint $1,$2,$3g' le 3 0
2 1
10 100 1000
1 5 7
取り出しはできましたが、2行目の出力が今までと異なります。これは、\awk"コマンド の 既定値で、要素間の区切りは\スペース" であると認識しているからです。このような出力形 式が気に入らない場合は\printf"を使って指定します。方法は後述します。
次に、行番号だけを表示してみます。
sophia% awk 'fprint NRg' le 3 0
2 1
1
2
さらに、行番号を付けてファイルの中の要素を取り出してみます。
sophia% awk 'fprint NR, $0g' le 3 0
2 1
1 10 100 1000
2 1 5 7
今度は、各行にいくつの要素があるかを調べます。
sophia% awk 'fprint NFg' le 3 0
2 1
3
3
今までの例を元に、次のような事が簡単に出来ます。
sophia% awk 'fprint "line", NR, "is", $0g' le 3 0
2 1
line 1 is 10 100 1000
line 2 is 1 5 7
このように、途中に文字列を挿入したい場合は、ダブルクォテーション(" ")でその文字列 を囲みます。
また、C言語と同じように条件文の記述が可能で、変数の値が数値の場合は、自動的に数値 の比較になります。
条件文 意味
a>b a は b より大きい
a<b a は b より小さい
a>=b a は b 以上
a<=b a は b 以下
a==b a と b は等しい
a!=b a と b は等しくない
a&&b a かつ b (論理積)
a||b a または b (論理和)
例1 2番目の要素が50より大きい行を出力
例2 2番目の要素が50より大きく、3番目の要素が4000より小さい行を出力
sophia% awk '$2>50 && $3<4000 fprintg' le 3 0
2 1
10 100 1000
例3 行番号が2にある全ての要素を出力
sophia% awk 'NR==2 fprintg' le 3 0
2 1
1 5 7
正規表現を使って、\7"という文字を検索し、その行の2番目の要素を取り出すには次のよ うに指定します。
sophia% awk '/7/ fprint $2g' le 3 0
2 1
5
C言語の printfと同様な書式付き出力もできます。
sophia% awk 'fprintf("line is %d,%s %s %snn",NR, $1, $2, $3)g' le 3 0
2 1
line 1 is, 10 100 1000
line 2 is, 1 5 7
書式 意味
%s 文字列として扱う
%d 整数として扱う
%f 小数点として扱う
nt タブ
nn 改行
\%s", \%d" 等の説明については、C言語関連の図書を参照してください。
少し慣れた所で、ちょっと高度な使い方をしてみましょう。データファイルの内容を次のよ うなものとします。
sophia% cat le 3 0
2 1
name syozoku bunrui shinchou taijuu deposit
---tanaka denki student 175 65 5000
sasaki center shokuin 170 60 4000
yabuki denki teacher 175 63 7000
fujiwara center shokuin 180 70 3000
miki sugaku student 170 60 1000
kuroe kagaku student 175 80 1000
また、別のファイルに次のような内容の記述があるとします。
sophia% cat le1 3 0
2 1
BEGIN {
printf("%10s %7s[cm]<n", "NAME", "SHINCHOU")
print "---"
}
NR > 2 {printf("%10s %7d[cm]<n", $1, $4)}
END {print "---"}
ここで次のようにコマンド を実行します。
sophia% awk -f le1 le 3 0
2 1
NAME SHINCHOU[cm]
---tanaka 175[cm]
sasaki 170[cm]
yabuki 175[cm]
fujiwara 180[cm]
miki 170[cm]
kuroe 175[cm]
上記の例では、はじめに、
NAME SHINCHOU[cm]
というヘッダを出力し、検索終了後、
を出力する、という意味になります。
この他にもいろいろな使い方ができます。詳しい使い方については、市販されている図書を 参照してください。