Go言語触りだして1周間位の初心者です。
PHPをずっと使っていて、勉強がてらApacheのアクセスログをパースして集計するコマンドをGo言語で書こうとしています。
Apacheのアクセスログは下記のような形式です。
unixtime:1447741976 datetime:17/Nov/2015:15:32:56 +0900 x-forwaded-for:123.123.123.123. host:234.234.234.234 size:13032 response_time:263564 status:200 server:100.100.100.100 Host:example.com method:GET path:/123 protocol:HTTP/1.1 UA:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 referer:https://www.google.co.jp/$ unixtime:1447741976 datetime:17/Nov/2015:15:32:56 +0900 x-forwaded-for:123.123.123.123 host:234.234.234.234 size:1478 response_time:15460 status:200 server:100.100.100.100 Host:example.com method:GET path:/456 protocol:HTTP/1.1 UA:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 referer:-$ 172.31.14.11 - - [17/Nov/2015:15:32:56 +0900] "GET /tag/14289 HTTP/1.1" 200 10898 "-" "Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)"$ unixtime:1447741976 datetime:17/Nov/2015:15:32:56 +0900 x-forwaded-for:123.123.123.123 host:234.234.234.234 size:1049 response_time:20953 status:200 server:100.100.100.100 Host:example.com method:GET path:/678 protocol:HTTP/1.1 UA:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 referer:-$ unixtime:1447741976 datetime:17/Nov/2015:15:32:56 +0900 x-forwaded-for:123.123.123.123 host:234.234.234.234 size:43 response_time:36534 status:200 server:100.100.100.100 Host:example.com method:GET path:/901 protocol:HTTP/1.1 UA:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 referer:-
1行ずつ読み込んで、各項目はタブで句切られてるのでタブでパースしてます。
その後値だけを取り出したいのでカンマでパースします。
下記のようにしてます。
Go
1package main 2 3import ( 4 "bufio" 5 "fmt" 6 "os" 7 "strings" 8) 9 10func main() { 11 logPath := "/path/to/log" 12 readOneRow(logPath) 13} 14 15func readOneRow(fileName string) { 16 var fp *os.File 17 var err error 18 fp, err = os.Open(fileName) 19 if err != nil { 20 panic(err) 21 } 22 defer fp.Close() 23 24 scanner := bufio.NewScanner(fp) 25 for scanner.Scan() { 26 // タブで分割 27 lineSplit := strings.Split(scanner.Text(), "\t") 28 29 // 例としてresponse_timeを取得したい 30 // 要素5 に入ってるので、そこを更にカンマでパースする 31 response_time := strings.Split(lineSplit[5], ":") 32 fmt.Println(response_time) 33 } 34 if err := scanner.Err(); err != nil { 35 panic(err) 36 } 37}
上記を実行するとログの3行目で「runtime error: index out of range」エラーになります。
3行目だけはタブ区切りになっておらず、形式が違うのでエラーになります。
そもそも何故こういう形式で出力されることがあるのか分かっていないのが問題ですが、99%以上は普通の行なので3行目のような行を無視出来たら楽だなと思ってます。
毎日数十万行のログが出力されるので手動チェックは厳しいです。
そこでPHPのissetのように5番目の要素が定義されていれば処理を続け、なければcontinueという分岐をいれたいと考えています。
Go
1 if !isset(lineSplit[5]) { // こんな処理を入れたい! 2 continue 3 } 4 response_time := strings.Split(lineSplit[5], ":") 5 fmt.Println(response_time)
Googleで検索してもほぼ出てきませんし、出てきても動かないものだったりです。
静的型付け言語初めてなのですが、こういう動作は可能なのでしょうか?
よろしくお願い申し上げます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/11/19 08:27