SlideShare uma empresa Scribd logo
1 de 67
Baixar para ler offline
AWKでちょっとしたテキストを

処理する方法。
AWKとは?
・Alfred Aho/Peter Weinberger/Brain Kernighanによって
 作られたシンタックス駆動型のパターンマッチング言語。
!
・Alfred Ahoいわく「AWKは一般的なデータ処理用の短い

 プログラムを記述するために設計されたスクリプティング言語」
A W K
※O REILLY「言語設計者たちが考えること」より
AWKの(個人的に考える)メリット。
・最初からテキストファイルを行xカラムに分けられる。
!
・行に対してのパターンマッチングが行える。
!
・学習コストが低い。
こんなデータを使います。
NO DATE NAME VAL
1 2013/01/01 23:59:12 aaa 20
2 2013/04/05 12:10:09 bbb 42
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
6 2013/03/23 20:12:23 zzz 9
・スペース区切りのTestData.txt、タブ区切りのTestData.tsv
取り敢えず実行してみよう。
・ファイルの中身が全てそのまま表示される。
> awk ‘{print $0}’ TestData.txt
NO DATE NAME VAL
1 2013/01/01 23:59:12 aaa 20
2 2013/04/05 12:10:09 bbb 42
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
6 2013/03/23 20:12:23 zzz 9
AWKの構造(1)
・awkは指定されたファイルの全ての行に命令文を繰り返す。
awk ‘{print $0}’ TestData.tsv
もう一度実行してみよう。
・今度はスペース区切り2カラム目と4カラム目が表示される。
・awkは自動的にスペース区切りでカラムを区切る。
・$iでiカラム目を選択可能。
・$0は全てのカラムという意味。
・上の文はTestData.txtの2カラム目と4カラム目を表示するという命令を

 全行にわたって繰り返せという意味。
>awk ‘{print $2,$4}’ TestData.txt
DATE VAL
2013/01/01 aaa
2013/04/05 bbb
2013/02/22 ccc
2013/06/19 abc
2013/10/09 bbc
2013/03/23 zzz
AWKの構造(2)
awk ‘BEGIN{}{print $0}END{}’ TestData.tsv
FSとOFS。
・FSとOFSは特殊な変数。
・どちらも区切り文字を指定するもの。
・FSはインプットファイルの区切り文字。
・OFSはアウトプットファイルの区切り文字。
・デフォルトではどちらもスペースになっている。
tsvファイルを開いてみよう。
・BEGINの部分にFS= t を入れる事で今後行われる命令文は全て
 タブ区切りテキストを対象にしている事を伝えている。
・タブ区切りテキストもちゃんと指定したカラムが表示される。
・7枚目のスライドと結果が微妙に違う事に注意。
> awk ‘BEGIN{FS= “t” }{print $2,$4}’ TestData.tsv
DATE VAL
2013/01/01 23:59:12 20
2013/04/05 12:10:09 42
2013/02/22 09:54:01 63
2013/06/19 04:45:12 120
2013/10/09 12:22:53 21
2013/03/23 20:12:23 9
tsvファイルをcsvファイルにしてみよう。
・BEGINの部分にOFS= , を入れる事で出力されるデータが
 カンマ区切りになる。
・ BEGIN{FS= t ;OFS= , }{print $0} ではどういう結果になるか試してみよう。
> awk ‘BEGIN{FS= “t” ;OFS= “,” }{print $1,$2,$3,$4}’
TestData.tsv > TestData.csv
>cat TestData.csv
NO,DATE,NAME,VAL
1,2013/01/01 23:59:12,aaa,20
2,2013/04/05 12:10:09,bbb,42
3,2013/02/22 09:54:01,ccc,63
4,2013/06/19 04:45:12,abc,120
5,2013/10/09 12:22:53,bbc,21
6,2013/03/23 20:12:23,zzz,9
ここまでのまとめ
NRとNF。
> awk ‘BEGIN{FS= “t” }{print NR,NF,$0}’ TestData.tsv
1 4 NODATE NAME VAL
2 4 1 2013/01/01 23:59:12 aaa 20
3 4 2 2013/04/05 12:10:09 bbb 42
4 4 3 2013/02/22 09:54:01 ccc 63
5 4 4 2013/06/19 04:45:12 abc 120
6 4 5 2013/10/09 12:22:53 bbc 21
7 4 6 2013/03/23 20:12:23 zzz 9
・NRは行番号、NFはフィールド数が格納される。
ここまでのまとめ(2)
AWKの構造(3)
・中括弧の前に条件式を置くことで中括弧の中の処理を行うか

 判別が出来る。
awk ‘EXPR{print $0}’
条件式 条件式が真なら実行される命令
条件式を使ってみよう(1)
・「4カラム目が20以下」の行を出力する。
・1行目と6行目は共に20以下なので出力される。
・それ以外の行は出力されない。
>awk ‘BEGIN{FS=” t” }$4 <= 20{print $0}’
1 2013/01/01 23:59:12 aaa 20
6 2013/03/23 20:12:23 zzz 9
条件式を使ってみよう(2)
・ //で正規表現でのマッチングが可能。
・最初の式は「3カラム目にbが含まれている」行を出力。
・2番目の式は「3カラム目がcで終わっている」行を出力。
>awk ‘BEGIN{FS=” t” }$3 ~ /b/{print $0}’
2 2013/04/05 12:10:09 bbb 42
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
>awk ‘BEGIN{FS=” t” }$3 ~ /c$/{print $0}’
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
条件式を使ってみよう(3)
・&&や¦¦で複数の条件を与えることも可能。
・最初の式は「3カラム目がcで終わっている」且つ「4カラム目が
 40より大きい」行を出力。
・2番目の式は「3カラム目がcで終わっている」或いは
 「4カラム目が20以下」の行を出力。
>awk ‘BEGIN{FS=” t” }$3 ~ /c$/ && $4 > 40{print $0}’
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
>awk ‘BEGIN{FS=” t” }$3 ~ /c$/ || $4 <= 20{print $0}’
1 2013/01/01 23:59:12 aaa 20
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
6 2013/03/23 20:12:23 zzz 9
条件式を使ってみよう(4)
・中括弧の数だけ処理が出来る。
・上の例では$4が偶数なら even という文字列と$4を出力。
・$4が奇数なら uneven という文字列と$4を出力。
>awk ‘BEGIN{FS=” t” }$4%2==0{print “even” ,$4}
$4%2==1{print “uneven” ,$4}’
even VAL
even 20
even 42
uneven 63
even 120
uneven 21
uneven 9
まとめるとこんな感じ。
BEGIN{
print “script start”
}
EXPR1{
print “hoge1” $0
}
EXPR2{
print “hoge2” ,$0
}
{
print “all” ,$0
}
END{
print “script end”
}
行が読まれる前に実行される。
EXPR1 が真なら実行される。
EXPR2 が真なら実行される。
全ての行で実行される。
全ての行が読み終わったら実行される。
AWKの構造(4)
awk -f test.awk TestData.tsv
・-fで命令文を書いたファイルを読みこませるとプログラムを
 外部ファイルにする事が出来る。
合計を求めてみよう。
・BEGINで変数を初期化、ENDで変数を出力。
・1行目はヘッダなので合計対象から外す。
sum.awk
> awk -f sum.awk TestData.tsv
275
if。
・sum.awkに条件をひとつ追加。1カラム目が奇数の時のみ
 合計対象とする。
if.awk
> awk -f if.awk TestData.tsv
104
for。
for(i=1;i<=10;i++){print i}
初期化式
継続条件式
再初期化式
・言わずと知れたループ構文。
・iに1を代入しループを開始する。
 iに1を加えながらiが10になるまでループを繰り返す。
for。
・個人的によく使うカラムチェックスクリプト。
・forで1カラム目からNカラム目までをナンバリングして
 1行ずつ出力する。
> awk -f for.awk TestData.tsv
1:1
2:2013/01/01 23:59:12
3:aaa
4:20
for.awk
split。
split(str,array,sep)
分割する文字列
分割した結果を格納する配列
区切り文字
・文字列を分割するための命令文。
・strに分割したい文字列を、arrayに格納したい配列を、
 sepに区切り文字を入れる。
split。
split.awk
> awk -f split.awk TestData.tsv
NO DATE TIME NAME VAL
1 2013/01/01 23:59:12 aaa 20
2 2013/04/05 12:10:09 bbb 42
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
6 2013/03/23 20:12:23 zzz 9
BEGIN{
FS="t";
OFS="t";
}
NR == 1{
print $1,$2,"TIME",$3,$4;
next;
}
{
split($2,datetime," ");
print $1,datetime[1],datetime[2],$3,$4;
}
split。
・日時を日付と時間に分割するスクリプト。
・$2をスペースで分割してdatetimeに放り込む。
・datetime[n]でn番目の要素にアクセス可能。
 つまり日付はdatetime[1]、時間はdatetime[2]。
split.awk
BEGIN{
FS="t";
OFS="t";
}
NR == 1{
print $1,$2,"TIME",$3,$4;
next;
}
{
split($2,datetime," ");
print $1,datetime[1],datetime[2],$3,$4;
}
変数と配列
・変数はひとつの容れ物にひとつの値。
・配列はひとつの容れ物を幾つかに分けてラベルをつけて格納する。
val
array
※ちなみにAWKの配列は連想配列。インデックスは数値じゃなくてもOK。
条件式を使ってみよう(5)
nr.awk
> awk -f nr.awk TestData.tsv
2 2013/04/05 12:10:09 bbb 42
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
$1==2,$1==5{
print $0
}
・条件式をカンマで2つ並べると最初の式が成り立ってから
 2番目の式が成り立つまでを実行する。
・上の例だと$1==2がなりたつ3行目から$1==5がなりたつ6行目
 までを実行する。
・$1が2,3,4,5の時に実行されるわけではない事に注意。
条件式を使ってみよう(5)
・$5==20の2行目から$5==21の6行目までが出力される。
nr2.awk
> awk -f nr.awk TestData.tsv
1 2013/01/01 23:59:12 aaa 20
2 2013/04/05 12:10:09 bbb 42
3 2013/02/22 09:54:01 ccc 63
4 2013/06/19 04:45:12 abc 120
5 2013/10/09 12:22:53 bbc 21
BEGIN{
FS="t";
OFS="t";
}
$4==20,$4==21{
print $0
}
縦横置換スクリプト
transpose.awk
BEGIN{
FS="t";
OFS="t";
}
{
for(i=1;i<=NF;i++){
val[i, NR] = $i;
}
}
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
}
縦横置換スクリプト読み解き
for(i=1;i<=NF;i++){
val[i, NR] = $i;
}
↓val[1,1] ↓val[2,1] ↓val[3,1] ↓val[4,1]
この for 文が何をしているか。
例えば今までと同様 TestData.tsv に対して実行してみると…。
データの最初の 1 行目は配列 val に以下の様に格納される。
2 行目はこんな感じに格納される。
↓val[1,2] ↓val[2,2] ↓val[3,2] ↓val[4,2]
縦横置換スクリプト読み解き
for(i=1;i<=NF;i++){
val[i, NR] = $i;
}
最終的には横がフィールド、縦が行数の配列が出来上がる。
フィールド
行数
val
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=1の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=2の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=3の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=4の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=5の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=6の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1/j=7の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=1の中のjのループが終わったのでprint “”で改行を行う。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=1の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=2の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=3の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=4の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=5の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=6の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2/j=7の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=2の中のjのループが終わったのでprint “”で改行を行う。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=1の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=2の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=3の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=4の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=5の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=6の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3/j=7の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=3の中のjのループが終わったのでprint “”で改行を行う。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=1の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=2の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=3の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=4の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=5の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=6の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4/j=7の時。
縦横置換スクリプト読み解き
END{
for(i=1;i<=NF;i++){
for(j=1;j<=NR;j++){
printf("%st",val[i,j]);
}
print "";
}
出力部分のfor部分を読み解いていくと…
 i=4の中のjのループが終わったのでprint “”で改行を行う。
縦横置換スクリプト読み解き
■i=1 で出力される項目。
■i=2 で出力される項目。
■i=3 で出力される項目。
■i=4 で出力される項目。

Mais conteúdo relacionado

Mais procurados

プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
Takuya Akiba
 
幾何コンテスト2013
幾何コンテスト2013幾何コンテスト2013
幾何コンテスト2013
Naoto Mizuno
 
指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端
Yoichi Iwata
 

Mais procurados (20)

自動定理証明の紹介
自動定理証明の紹介自動定理証明の紹介
自動定理証明の紹介
 
プログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズムプログラミングコンテストでの乱択アルゴリズム
プログラミングコンテストでの乱択アルゴリズム
 
Nazoki
NazokiNazoki
Nazoki
 
Λέξεις κλειδιά για αφαίρεση-πρόσθεση
Λέξεις κλειδιά για αφαίρεση-πρόσθεσηΛέξεις κλειδιά για αφαίρεση-πρόσθεση
Λέξεις κλειδιά για αφαίρεση-πρόσθεση
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
 
JavaScriptでSQLを唱えたいだけの人生だった
JavaScriptでSQLを唱えたいだけの人生だったJavaScriptでSQLを唱えたいだけの人生だった
JavaScriptでSQLを唱えたいだけの人生だった
 
AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説
 
すごい配列楽しく学ぼう
すごい配列楽しく学ぼうすごい配列楽しく学ぼう
すごい配列楽しく学ぼう
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
 
abc032
abc032abc032
abc032
 
幾何コンテスト2013
幾何コンテスト2013幾何コンテスト2013
幾何コンテスト2013
 
Mov is turing-complete
Mov is turing-completeMov is turing-complete
Mov is turing-complete
 
指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端指数時間アルゴリズムの最先端
指数時間アルゴリズムの最先端
 
AtCoder Beginner Contest 028 解説
AtCoder Beginner Contest 028 解説AtCoder Beginner Contest 028 解説
AtCoder Beginner Contest 028 解説
 
充足可能性問題のいろいろ
充足可能性問題のいろいろ充足可能性問題のいろいろ
充足可能性問題のいろいろ
 
続・わかりやすいパターン認識第5章
続・わかりやすいパターン認識第5章続・わかりやすいパターン認識第5章
続・わかりやすいパターン認識第5章
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
定理証明支援系Coqについて
定理証明支援系Coqについて定理証明支援系Coqについて
定理証明支援系Coqについて
 
WSL2+docker+JupyterとVS Codeリモート環境の構築
WSL2+docker+JupyterとVS Codeリモート環境の構築WSL2+docker+JupyterとVS Codeリモート環境の構築
WSL2+docker+JupyterとVS Codeリモート環境の構築
 
最大流 (max flow)
最大流 (max flow)最大流 (max flow)
最大流 (max flow)
 

Awk勉強会用資料