Skip to content

Instantly share code, notes, and snippets.

@callmekohei
Created June 1, 2019 11:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save callmekohei/3b2067456cdae97ae273a6aafe4745d6 to your computer and use it in GitHub Desktop.
Save callmekohei/3b2067456cdae97ae273a6aafe4745d6 to your computer and use it in GitHub Desktop.
@ytez さんによる AWK の練習問題

@ytez さんによる AWK の練習問題

1) 各行に連番を振る(ヒント: NR)
2) 大文字→小文字の変換, その逆(ヒント: toupper,tolower)
3) 2文字目〜5文字目だけを切り出す (ヒント: substr)
4) foo を bar に置換する (ヒント: sub)
5) 奇数行だけ取り出す (ヒント: NR%2)

callmekoheiの回答

### 1) 各行に連番を振る(ヒント: NR)
seq 10 15 | awk '{ print NR " => " $0 }'

### 2) 大文字→小文字の変換, その逆(ヒント: toupper,tolower)
echo 'ABC' | awk '{print tolower($0)}'
# abc
echo 'abc' | awk '{print toupper($0)}'
# ABC

### 3) 2文字目〜5文字目だけを切り出す (ヒント: substr)
echo 'abcdefg' | awk '$0 = substr($0, 2,5)'

### 4) foo を bar に置換する (ヒント: sub)
echo "foo bar baz" | awk '{ sub(/foo/ , "bar"); print $0 }'
# bar bar baz 

### 5) 奇数行だけ取り出す (ヒント: NR%2)
seq 10 15 | awk '{if(NR%2 == 0) {print $0}}'
@callmekohei
Copy link
Author

ytezさんのアドバイスっ

BEGIN{
  FS=","
 OFS=","
}
{
  $2=ymd($2);$4=ymd($4); print $0
}

function ymd(yyyymmdd,    y, m, d) { # ← ここだいじ
  y = substr(yyyymmdd,0,4)
  m = substr(yyyymmdd,5,2)
  d = substr(yyyymmdd,7,2)
  return y "-" m "-" d
}

@callmekohei
Copy link
Author

A0011223344,2019-04-30,りんご,2018-07-31
A0011223345,2018-04-30,サクランボ,2017-02-24
A0011223348,2029-03-21,ばなな,2011-02-22

@callmekohei
Copy link
Author

callmekohei commented Jun 14, 2019

AWKを実務で使ってみた!

任意の 'CSV' から特定の列を抜き出し
3列目 1stソート、1列目で 2ndソート
3列目の重複を削除して
1列目でソートする
1行目を削除する

cat *.csv \
  | cut -d ',' -f 2,7,9,13,19 \
  | LC_ALL='C' sort -t , -k 3,3 -k 1r,1  \
  | awk -F, '{if (!a[$3]++) { print $0 } }' \
  | LC_ALL='C' sort -t , -k 1r,1 \
  | sed -e '1d' \
  > foo.csv

@callmekohei
Copy link
Author

AWKにおける Uniq

上記の復習

Awk's boolean

Status Value
False "" or 0
True Other than those above

Awk's dictionary

dict["apple"] = a
dict["apple"] = b
print dict["apple"] 
# // => b

foo.csv

aaa,123,apple
bbb,456,banana
aaa,789,cherry
ccc,111,lemon
aaa,222,laichi
ddd,333,carrot
aaa,444,grape

foo.bash

cat foo.csv \
  | sort -t, -k 1,1 \
  | awk -f ./foo.awk \

foo.awk

#! /usr/local/bin/awk
BEGIN{
   FS=","
  OFS=","
}
{
  if ( !dict[$1]++ )
    print $0
}

実行結果

aaa,123,apple
bbb,456,banana
ccc,111,lemon
ddd,333,carrot

上記awkコードの意味
ytezさんのツイートを参考に・・・

ポイントは、boolean , dict そして postIncr のところ 

awkのfalseはゼロもしくは空文字のみ。他はすべてtrue

dict(連想配列)は  dict["foo"] と表現する

dict["foo"]++ と後置インクリメンタルすることで
評価された後で下記を実行する
dict["foo"] = dict["foo"] + 1 

@callmekohei
Copy link
Author

callmekohei commented Jun 15, 2019

上記の補足( ytezさんによる補題)

最初にヒットしたaaa以外を出力する

#! /usr/local/bin/awk
BEGIN{
   FS=","
  OFS=","
}
{
  if ( !( dict[$1]++ <= 0 ) )
    print $0
}

結果

aaa,222,laichi
aaa,444,grape
aaa,789,cherry

@callmekohei
Copy link
Author

さらに上記の追記

  if ( !( dict[$1]++ <= 0 ) ) # 2行目以降
  if ( !( dict[$1]++ <= 1 ) ) # 3行目以降
  if ( !( dict[$1]++ <= 2 ) ) # 4行目以降
  if ( !( dict[$1]++ <= 3 ) ) # 5行目以降

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment