Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
152
Help us understand the problem. What is going on with this article?
@hirohiro77

AWKのこういう時はどう書く?

More than 3 years have passed since last update.

linuxのコマンドラインでデータ加工をする際によく使うAWKですが、個人的につまずいた使い方について、
覚え書きとして残します。誰かの助けになれば…

  • 組み込み関数覚え書き
 FS        入力フィールドセパレータ(空白とタブ)
 CNVFMT        数値を文字列に変換するフォーマット
 OFMT          数字の出力フォーマット(%.6g)
 OFS           出力フィールドセパレータ(空白) 
 ORS           出力レコードセパレータ(\n)
 RS        入力レコードセパレータ(\n) 
 SUBSEP        配列添字セパレータ(\034)
 ARGC          コマンド行の引数の数+1
 ARGV          コマンド行の引数の配列 
 ENVIRON["..."] 環境変数の値 
 FILENAME       入力ファイル名 
 FNR           入力ファイルの通算レコード 
 NF        入力レコードのフィールド数 
 NR        入力レコード総数
 RLENGTH       matchで適合した文字列の長さ 
 RSTART        matchで適合した文字列の開始位置 
  • セパレータを指定して処理したい
# -Fでセパレータを指定
awk -F ":" '{ print $1 " " $3 }' /etc/passwd

root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
uucp 10
operator 11

  • 各フィールドをループしたい
awk '{for (i = 1; i <= NF; i++) print $i;}' data.txt
  • 複数の記号をセパレータとして使用したい
#正規表現を使用するとできる
#以下はスペースと:と/を区切り文字として使用した場合の例

echo "2016/03/01 12:12:12" | awk -F'[ :/]' '{print $2}'
  • 特定の正規表現のパターンにマッチする行だけ処理する
awk -F':' '$0 ~ /root/{ print}' /etc/passwd
  • 文字列を数値に変換する
#特に何もする必要がない。数値を表した文字列は数値に自動的に変換される。
echo | awk '{ x="1.01"; x=x+1; print x}'
2.01
  • 部分文字列を作成する
echo 'abcde' | awk '{print substr($0, 2)}'
  • 特定の制御文字でフィールドを区切る
#下の例では^Aの部分が制御文字
#^Aの場合はCtrl+v Ctrl+Aでターミナル上から入力できる

more control_code.txt

a^Ab

awk -F'^A' '{print $1 ":" $2}' control_code.txt

a:b

#バイナリの値を以下のように指定する事もできる

awk -F'\01' '{print $1 ":" $2}' control_code.txt 

a:b
  • csvのカラム数が8個の行だけ抽出
8get.awk
BEGIN {
while (getline < "/work/test.csv" > 0) {
    col = split($0,field,",")
    if ( col == 8  ) print $0
    }
    close("/work/test.out.csv");
}

実行

gawk -f /work/8get.awk
  • ゼロパディング(ゼロ埋め)
echo "1" | awk '{printf "%02d", $1}'
> 01
  • フォーマット変換
# xを○○に変換

printf("%d\n",x)               #整数として出力
printf("%5d\n",x)              #5桁で右詰の整数として出力
printf("%e\n",x)               #浮動小数点数(eの後の数字は10の累乗を表す)
printf("%7.2f\n",x)            #浮動小数点数、7桁で小数第2位まで
printf("%6.2f\n",x)            #浮動小数点数、6桁で小数第2位まで
printf("%5.2f\n",x)            #浮動小数点数、5桁で小数第2位まで
printf("%4.2f\n",x)            #浮動小数点数、4桁で小数第2位まで
printf("%o\n",x)               #8進数として出力
printf("%x\n",x)               #16進数として出力
printf("%c\n",x)               #文字コードして対応するアルファベットを出力
printf("%s\n",x)               #そのまま文字列として出力
printf("%10s\n",x)             #右詰で10桁のスペースに出力
printf("%-10s\n",x)            #左詰で10桁のスペースに出力
printf("%.3s\n",x)             #左詰で3文字のみ出力
printf("%10.3s\n",x)           #右詰で10桁のスペースに3文字を出力
printf("%-10.3s\n",x)          #左詰で10桁のスペースに3文字を出力

#ワンライナーで使う場合は以下のように置き換えればOK
echo 12345 | awk '{ printf("%-10.3s\n",$0) }'

ちょっと穿った使い方

  • ファイルを結合してみる(inner join風)

使うワンライナーはこんな感じ

awk 'F==0{a[$1]=$2;next}{print $1 "\t" a[$1] "\t" $2}' data1.tsv F=1 data2.tsv

data1.tsv と data2.tsvの1カラム目を比較して、おなじだったら、カラムを右に結合
例として、以下のような2つのtsvがあったとして、上記のコマンドを打つと、結果が以下のように出る
joinのほうが絶対簡単だと思うけれど、awkでやってみたいと思ったので、やってみた。

data1.tsv
a 100
b 200
c 250
d 500
data2.tsv
a red
d black
b blue
c green
b blue
d black
結果
a       100     red
d       500     black
b       200     blue
c       250     green
b       200     blue
d       500     black
152
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
hirohiro77
インフラ屋さんやってます。構成の設計とか、仮想サーバのお守とか、システムのマイナーアップデートとか、監視など。 [[ また、このサイトにおける掲載内容はあくまで私自身の見解であり、私の所属団体・企業における立場、戦略、意見を代表するものではありません ]]
opt
"INNOVATION AGENCY" を標榜するインターネット広告代理店。エンジニア組織 "Opt Techonologies" を中心にアドテクetc...に取り組んでいます。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
152
Help us understand the problem. What is going on with this article?