データ処理-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