データ処理-1
参考書籍 : 実践bashによるサイバーセキュリティ対策
・利用するコマンド
1, awk
-f : 指定したファイルからawkプログラムを読み込む
awkは入力された各行を順に処理し、空白で区切られた単語を順にフィールドに格納する。
フィールド$0は行全体を表し、$1は最初の単語、$2は次の単語を表す。
次のawkusers.txtをawkで処理する。
awkusers.txt
Mike Jones John Smith Kathy Jones Jane Kennedy Tim Scott
awkで姓がJonesとなっているユーザの行を表示する
$ awk '$2 == "Jones" {print $0}' awkusers.txt Mike Jones Kathy Jones
awkはパターンと、パターンにマッチした際に実行されるコードの組から構成されている。
この場合のパターンは、$2 == "Jones"で、処理は{print $0}である。
2, join : 2つのファイルの共通のフィールドがある行を結合する。
-j : 指定したフィールド番号を用いて結合を行う
-t ; フィールドのデリミタとして用いる文字を指定する
--header ; 各ファイルの先頭行をヘッダとみなす
次の2つのtxtファイルを結合する。
accesstime.txt
0745,file1.txt,1 0830,file4.txt,2 0830,file5.txt,3
usernames.txt
1,jdoe 2,puser 3,jsmith
以下のコマンドを実効する。
$ join -1 3 -2 1 -t, accesstime.txt usernames.txt 1,0745,file1.txt,jdoe 2,0830,file4.txt,puser 3,0830,file5.txt,jsmith
- 1 3 で1つ目のファイル(accesstime.txt)の3つめのカラムを結合時に使用する。
- 2 1 で2つ目のファイル(usernames.txt)の1つめのカラムを結合時に使用する。
- t , で区切り文字が,になる。
3, sed : 文字列の置換などを行う
-t : 指定したファイルを編集し、その場で上書きする。
ips.txtに対し、10.0.4.35というIPアドレスをすべて10.0.4.27に置換する。
ip,OS 10.0.4.2,Windows 8 10.0.4.35,Ubuntu 16 10.0.4.107,macOS 10.0.4.145,macOS
$ sed 's/10\.0\.4\.35/10.0.4.27/g' ips.txt ip,OS 10.0.4.2,Windows 8 10.0.4.27,Ubuntu 16 10.0.4.107,macOS 10.0.4.145,macOS
この例では、's/正規表現/置換後の文字列/フラグ'のフォーマットを用いている。
4, tail : 末尾を出力
-f : ファイルを継続的に監視し、追加された行を出力する
-n : 指定された行数を出力する(デフォルトは10)
5, tr : ある文字を別の文字に置換
-d : 入力ストリームから指定した文字を取り除く
-s : 同じ文字が連続して出現したときに、一文字に短縮する。
不要な文字を削除するときに使われることが多い。
infile.txtの\(バックスラッシュ)を/(スラッシュ)に、:(コロン)を|に変換する例を示す。
infile.txt
drive:path\name c:\Users\Default\file.txt
$ tr '\\:' '/|' < infile.txt drive|path/name c|/Users/Default/file.txt
trはエスケープ文字(\nなど)を使用可能なので、\(バックスラッシュ)を表現するときには\\とする。
・デリミタ付きファイルの処理
1, 表示処理
,(コンマ)で区切られたCSVファイルの処理を考える。
以下にCSVファイルの例を示す。
csvex.txt
"name","username","phone","password hash" "John Smith","jsmith","555-555-1212",5f4dcc3b5aa765d61d8327deb882cf99 "Jane Smith","jnsmith","555-555-1234",e10adc3949ba59abbe56e057f20f883e "Bill Jones","bjones","555-555-6789",d8578edf8458ce06fbc5bb76a58c5ca4
先頭行はヘッダとなっている。
name列を抽出するには、cutを用いる
$ cut -d',' -f1 csvex.txt "name" "John Smith" "Jane Smith" "Bill Jones"
"で囲まれたままであるので、trで不要な文字を除去する。
$ cut -d',' -f1 csvex.txt | tr -d '"' name John Smith Jane Smith Bill Jones
tailを使い、ヘッダを表示しないようにできる。
$ cut -d',' -f1 csvex.txt | tr -d '"' | tail -n +2 John Smith Jane Smith Bill Jones
tailは-nオプションに+がついていると、指定した数値を開始行として出力する。
2, awkを用いた繰り返し処理
csvex.txtに格納されている各ユーザのパスワードハッシュを、passwords.txtと突き合わせてチェックする場合を考える
passwords.txt
password,md5hash 123456,e10adc3949ba59abbe56e057f20f883e password,5f4dcc3b5aa765d61d8327deb882cf99 welcome,40be4e59b9a2a2b5dffb918c0e86b3d7 ninja,3899dcbab79f92af727c2190bbd8abc5 abc123,e99a18c428cb38d5f260853678922e03 123456789,25f9e794323b453885f5181f1b624d0b 12345678,25d55ad283aa400af464c76d713c07ad sunshine,0571749e2ac330a7455809c6b0e7af90 princess,8afa847f50a716e64932d995c8e7435a qwerty,d8578edf8458ce06fbc5bb76a58c5ca4
awkを用いて、各ユーザのパスワードハッシュをcsv.txtから抽出する。
$ awk -F "," '{print $4}' csvex.txt "password hash" 5f4dcc3b5aa765d61d8327deb882cf99 e10adc3949ba59abbe56e057f20f883e d8578edf8458ce06fbc5bb76a58c5ca4
さらにgrepを用いて、awkの出力を1行ずつpasswords.txtの内容とマッチさせ、マッチした内容を出力する。
$ grep "$(awk -F "," '{print $4}' csvex.txt)" passwords.txt 123456,e10adc3949ba59abbe56e057f20f883e password,5f4dcc3b5aa765d61d8327deb882cf99 qwerty,d8578edf8458ce06fbc5bb76a58c5ca4