読者です 読者をやめる 読者になる 読者になる

Learn to Live and Live to Learn

IT(たまにビジネス)に関する記事を読んで、考えて、使ってみたことをまとめる場。

Shell Scriptで正規表現

shell スクリプトでファイルから1行ずつ読み込んだデータを正規表現を使って欲しい情報のみを別のファイルに書き出す 2 - xai1981's blog
を読んでいて、正規表現と言うとPerlを連想してしまうのですが、Shell Scriptでもできる!と知ったので(むしろ今までできることに気付かなかった)やってみました。

正規表現

expr "対象文字列" : "マッチさせるパターン"

マッチした位置や()でグループ化した結果を出力します。
今回はいらないので/dev/nullに捨てます。
http://qiita.com/Linda_pp/items/31fa611766598715a172

実行

使用したデータ、スクリプト、実行結果です。
やっていることは読んだ記事とほぼ同じですので、ご興味がありましたら以下読んでみてくださいー。

使用データ
$ cat input/access.log-20131212 
www.hoge.com 1.1.1.1 - - "POST /user/aaaaa HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "POST /user/bbbbb HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /hoge HTTP/1.1" 200 9570 ...
www.hoge.com 1.1.1.1 - - "POST /user/ccccc HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /photo HTTP/1.1" 302 5 ...
www.hoge.com 1.1.1.1 - - "POST /user/ddddd HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "POST /user/eeeee HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /bar HTTP/1.1" 200 779 ...
www.hoge.com 1.1.1.1 - - "POST /foo HTTP/1.1" 200 313 ...
www.hoge.com 1.1.1.1 - - "GET / HTTP/1.1" 200 20912 ...
www.hoge.com 1.1.1.1 - - "GET /hoge HTTP/1.1" 302 5 ...
www.hoge.com 1.1.1.1 - - "GET /video/100 HTTP/1.1" 200 74 ...
www.hoge.com 1.1.1.1 - - "GET /video/100 HTTP/1.1" 200 74 ...
$ cat input/access.log-20131213
www.hoge.com 1.1.1.1 - - "POST /user/AAAAA HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "POST /user/BBBBB HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /hoge HTTP/1.1" 200 9570 ...
www.hoge.com 1.1.1.1 - - "POST /user/CCCCC HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /photo HTTP/1.1" 302 5 ...
www.hoge.com 1.1.1.1 - - "POST /user/DDDDD HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "POST /user/EEEEE HTTP/1.1" 200 61 ...
www.hoge.com 1.1.1.1 - - "GET /bar HTTP/1.1" 200 779 ...
www.hoge.com 1.1.1.1 - - "POST /foo HTTP/1.1" 200 313 ...
www.hoge.com 1.1.1.1 - - "GET / HTTP/1.1" 200 20912 ...
www.hoge.com 1.1.1.1 - - "GET /hoge HTTP/1.1" 302 5 ...
www.hoge.com 1.1.1.1 - - "GET /video/100 HTTP/1.1" 200 74 ...
www.hoge.com 1.1.1.1 - - "GET /video/100 HTTP/1.1" 200 74 ...
スクリプト

POSTを使っているユーザ=POST /user/<ここ>を抜き出す。

$ cat analysis_log.sh 
#!/usr/bin/bash

for current_file in `ls input`
do
	cnt=1
	
	# read関数を使いパイプで受け取ったものを$lineに格納。
	# http://d.hatena.ne.jp/r_ikeda/20110503/read
	cat input/${current_file} | while read line
	do

		# 現在どこを処理しているか表示。
		echo File: $current_file Line: $cnt
		
		if expr "$line" : ".*POST /user/[a-zA-Z].*" > /dev/null; then

			# ×$1 ○1
			echo $line | sed -e "s/.*POST \/user\/\([a-zA-Z]*\).*/\1/g" >> output/$current_file

		fi

		# shell scriptは変数の値を文字列として扱う。
		# 数字の演算だと示すためletを使用。
		# let cnt = $cnt + 1とスペースを空けて書くとcntも関数だと思われてしまう。
		# http://ameblo.jp/oyasai10/entry-10895223731.html
		# http://d.hatena.ne.jp/JOlantern/20111202/1322821849
		let cnt=$cnt+1
	done
done

*1

実行結果
$ sh analysis_log.sh 
File: access.log-20131212 Line: 1
File: access.log-20131212 Line: 2
File: access.log-20131212 Line: 3
File: access.log-20131212 Line: 4
File: access.log-20131212 Line: 5
File: access.log-20131212 Line: 6
File: access.log-20131212 Line: 7
File: access.log-20131212 Line: 8
File: access.log-20131212 Line: 9
File: access.log-20131212 Line: 10
File: access.log-20131212 Line: 11
File: access.log-20131212 Line: 12
File: access.log-20131212 Line: 13
File: access.log-20131213 Line: 1
File: access.log-20131213 Line: 2
File: access.log-20131213 Line: 3
File: access.log-20131213 Line: 4
File: access.log-20131213 Line: 5
File: access.log-20131213 Line: 6
File: access.log-20131213 Line: 7
File: access.log-20131213 Line: 8
File: access.log-20131213 Line: 9
File: access.log-20131213 Line: 10
File: access.log-20131213 Line: 11
File: access.log-20131213 Line: 12
File: access.log-20131213 Line: 13
$ cat output/access.log-2013121* | head
aaaaa
bbbbb
ccccc
ddddd
eeeee
AAAAA
BBBBB
CCCCC
DDDDD
EEEEE

*1:正規表現の「+」が上手く効かなかったのでどこを書き間違えたか、原因がわかりましたら追記します。