awkawkを使い始める


備考

AWKという名前は、クリエイターのAlfred V. Aho、Peter J. Weinberger、
Brian W. Kernighan。

リソース

バージョン

初期バージョンバージョン発売日
POSIX awk 1992年 IEEE Std 1003.1、2013 Edition 2013年4月19日
1つのTrue AwkまたはNawkまたはBWK awk 198X - 2012年12月20日
GNU awkまたはgawk 1986 4.1.3 2015-05-19

例によるAWK

AWKは文字列操作言語で、主にUNIXシステムで使用されます。 AWKの背後にあるアイデアは、あまりにも複雑ではないファイルで作業するときに使用する多彩な言語を作成することでした。

AWKにはいくつかの変種がありますが、主なコンセプトは同じで、追加機能があります。これらの他の変種はNAWKとGAWKです。 GAWKには、両方の機能がすべて含まれていますが、NAWKはAWKの1ステップ上です。

AWKを考える最も簡単な方法は、それが2つの主要な部分を持っていると考えることです。パターンとアクション。

おそらくAWKの最も基本的な例です:(Hello Worldも参照してください)

BEGIN {print "START"}
      {print        }
END   {print "STOP" }
 

ここではキーワードBEGINEND がパターンであり、アクションは{}の内部にあります。この例は役に立たないかもしれませんが、実際にこれを有用な関数にするのは軽微な変更だけです。

BEGIN {print "File\tAuthor"}
      {print $8, "\t", $3}
END {print " - DONE - "}
 

ここで、 \t はタブ文字を表し、出力行の境界を一様に上げるために使用されます。 $ 8と$ 3は、 Shell Scripts で使用されているものと似ていますが、3番目と8番目の引数を使用する代わりに、入力行の3番目と8番目の列を使用します。

したがって、この例では、上の行にFile Author、二番目の行にはファイルパスが表示されます。 $ 8はファイルの名前、$ 3は所有者です(ディレクトリパスを見ると、これはより明確になります)。最後に、期待通りに最終行が印刷されます - DONE -

上記の例のクレジットはhttp://www.grymoire.com/Unix/Awk.htmlにあります

参照ファイル

Greg Goebelのcoins.txt

gold     1    1986  USA                 American Eagle
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona
silver  10    1981  USA                 ingot
gold     1    1984  Switzerland         ingot
gold     1    1979  RSA                 Krugerrand
gold     0.5  1981  RSA                 Krugerrand
gold     0.1  1986  PRC                 Panda
silver   1    1986  USA                 Liberty dollar
gold     0.25 1986  USA                 Liberty 5-dollar piece
silver   0.5  1986  USA                 Liberty 50-cent piece
silver   1    1987  USA                 Constitution dollar
gold     0.25 1987  USA                 Constitution 5-dollar piece
gold     1    1988  Canada              Maple Leaf
 

最小理論

一般的なawk one-liner:

awk <awk program> <file>
 

または:

<shell-command> | awk <awk program> 
 

<shell-command><file>awk入力として扱われます

<awk program> はこのテンプレートに続くコードです(単一で二重引用符ではありません):

'BEGIN   {<init actions>};
 <cond1> {<program actions>};
 <cond2> {<program actions>};
 ...
 END  {<final actions>}'
 

ここで:

  • <condX> 条件はawkの入力行と一致することが最も多い正規表現/re/ です。
  • <* actions> はCのような構造を備えたシェルコマンドと同様の一連のステートメントです。

``は以下の規則に従って処理されます:
  1. BEGIN ...END ... はオプションで、awk入力行の処理の前後に実行されます。
  2. awk入力の各行について、条件<condN> が肉の場合、関連する<program actions> ブロックが実行されます。
  3. {<program actions>} 既定値は{print $0} です。

条件は、標準の論理演算子と組み合わせることができます。

    /gold/ || /USA/ && !/1986/
 

ここで&&|| を優先する;

print ステートメントprint item1 item2 ステートメントを印刷すると、STDOUTに項目が出力されます。
項目は、変数( X$0 )、文字列( "hello")または数値です。
item1, item2 は、 OFS 変数の値と照合されます。
item1 item2 はジャストポスト !スペースはitem1 " " item2 を、その他の機能はprintfを使用してください。

変数$ 必要としませんprint myVar; つまり、 print myVar;
awkには以下の特殊変数が組み込まれています:

  • FS :フィールド内のawk入力行を分割するためのフィールド区切りとして機能します。私は単一の文字にすることができます、 FS="c" ;ヌル文字列、 FS="" (各文字は個別のフィールドになります)。スラッシュのない正規表現FS="re" ; FS=" " は空白とタブの実行を表し、デフォルト値です。
  • NF :読み込むフィールドの数。
  • $1$2 、...:第1フィールド、第2フィールド。現在の入力回線の回線番号、
  • $0 :現在の入力行。
  • NR :現在の入力行番号。
  • OFS :印刷時にフィールドを照合する文字列。
  • ORS :出力レコードセパレータ。デフォルトで改行。
  • RS :ライン(レコード)セパレータを入力します。デフォルトは改行です。 FS として設定します。
  • IGNORECASE :正規表現があるときFSとRSに影響を与えます。

regexp gold 行をフィルタリングし、それらを数えます:

# awk 'BEGIN {print "Coins"} /gold/{i++; print $0}  END {print i " lines out of " NR}' coins.txt
Coins
gold     1    1986  USA                 American Eagle      
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona 
gold     1    1984  Switzerland         ingot 
gold     1    1979  RSA                 Krugerrand 
gold     0.5  1981  RSA                 Krugerrand 
gold     0.1  1986  PRC                 Panda                       
gold     0.25 1986  USA                 Liberty 5-dollar piece
gold     0.25 1987  USA                 Constitution 5-dollar piece
gold     1    1988  Canada              Maple Leaf
9 lines out of 13
 

デフォルトのprint $0 内部awk変数に基づいたアクションと条件NR

# awk 'BEGIN {print "First 3 coins"} NR<4' coins.txt
First 3 coins                                                  
gold     1    1986  USA                 American Eagle         
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona 
silver  10    1981  USA                 ingot
 
Cスタイルの `printf`による書式設定:
# awk '{printf ("%s \t %3.2f\n", $1, $2)}' coins.txt
gold     1.00                                      
gold     1.00                                      
silver   10.00                                     
gold     1.00                                      
gold     1.00                                      
gold     0.50                                      
gold     0.10                                      
silver   1.00                                      
gold     0.25                                      
silver   0.50                                      
silver   1.00                                      
gold     0.25                                      
gold     1.00
 

条件の例

awk 'NR % 6'            # prints all lines except those divisible by 6
awk 'NR > 5'            # prints from line 6 onwards (like tail -n +6, or sed '1,5d')
awk '$2 == "foo"'       # prints lines where the second field is "foo"
awk '$2 ~ /re/'         # prints lines where the 2nd field mateches the regex /re/
awk 'NF >= 6'           # prints lines with 6 or more fields
awk '/foo/ && !/bar/'   # prints lines that match /foo/ but not /bar/
awk '/foo/ || /bar/'    # prints lines that match /foo/ or /bar/ (like grep -e 'foo' -e 'bar')
awk '/foo/,/bar/'       # prints from line matching /foo/ to line matching /bar/, inclusive
awk 'NF'                # prints only nonempty lines (or: removes empty lines, where NF==0)
awk 'NF--'              # removes last field and prints the line
 

アクション{...} 追加することで、行全体ではなく特定のフィールドを印刷することができます。

awk '$2 ~ /re/{print $3 " " $4}'
 

2番目のフィールドがregex / re /とマッチする行の3番目と4番目のフィールドを表示します。

いくつかの文字列関数

substr() 関数:

# awk '{print substr($3,3) " " substr($4,1,3)}' 
86 USA                                            
08 Aus                                            
81 USA                                            
84 Swi                                            
79 RSA                                            
81 RSA                                            
86 PRC                                            
86 USA                                            
86 USA                                            
86 USA                                            
87 USA                                            
87 USA                                            
88 Can                                            
 

match(s, r [, arr]) は、正規表現r が発生するs の位置を返し、 RSTARTRLENGTH 値を設定します。引数arr が指定されている場合は、配列arr が返されます。この場合、要素は括弧で囲まれた部分式にマッチします。 arr の0番目の要素マッチは、正規表現マッチ全体に設定されます。式arr[n, "start"] およびarr[n, "length"] は、一致する各部分文字列の開始位置と長さを指定します。

より多くの文字列関数:

sub(/regexp/, "newstring"[, target])
gsub(/regexp/, "newstring"[, target])
toupper("string")
tolower("string")
 

ステートメント

簡単なステートメントは、多くの場合、次のいずれかです。

variable = expression 
print [ expression-list ] 
printf format [ , expression-list ] 
next # skip remaining patterns on this input line
exit # skip the rest of the input
 

stat1stat2 がステートメントの場合、次もステートメントです。

{stat}

{stat1;  stat2}

{stat1 
stat2}

if ( conditional ) statement [ else statement ]
 

次のCのような標準的な構文は、文です。

if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
break    # usual C meaning 
continue # usual C meaning 
 

フィールド4から始まる可変長の記述要素を出力するCスタイルのループ。

# awk '{out=""; for(i=4;i<=NF;i++){out=out" "$i}; print out}' coins.txt
USA American Eagle                    
Austria-Hungary Franz Josef 100 Korona
USA ingot                             
Switzerland ingot                     
RSA Krugerrand                        
RSA Krugerrand                        
PRC Panda                             
USA Liberty dollar                    
USA Liberty 5-dollar piece            
USA Liberty 50-cent piece             
USA Constitution dollar               
USA Constitution 5-dollar piece       
Canada Maple Leaf
 

i は0に初期化されていることに注意してください。

ヌニックフィールドに条件と計算を適用する場合:

# awk '/gold/ {if($3<1980) print $0 "$" 425*$2}' coins.txt    
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona      $425
gold     1    1979  RSA                 Krugerrand                  $425   
 

AWK実行可能スクリプト

#!/usr/bin/gawk -f
# This is a comment
(pattern) {action}
...
 

シェル変数を渡す

# var="hello"
# awk -v x="$var" 'BEGIN {print x}'
hello
 

こんにちは世界

Hello worldの例は次のように簡単です:

awk 'BEGIN {print "Hello world"}'
 

最も基本的なawk プログラムは真の値(通常は1 )で構成され、 awk は入力をエコーし​​ます:

$ date | awk '1'
Mon Jul 25 11:12:05 CEST 2016
 

「こんにちは世界」もまた真の価値だから、次のように言うこともできます:

$ date | awk '"hello world"'
Mon Jul 25 11:12:05 CEST 2016
 

しかし、あなたが書くと、あなたの意図ははるかに明確になります

$ date | awk '{print}'
Mon Jul 25 11:12:05 CEST 2016
 

代わりに。

AWKプログラムの実行方法

プログラムが短い場合は、awkを実行するコマンドに含めることができます。

awk -F: '{print $1, $2}' /etc/passwd
 

この例では、コマンドラインスイッチ-F: を使用して、入力フィールド区切り文字として-F: をawkに使用することをお勧めします。同じですか?

awk 'BEGIN{FS=":"}{print $1,$2}' file
 

代わりに、awkコード全体をawkファイルに保存し、このawkプログラムを次のように呼び出すことができます:

awk -f 'program.awk' input-file1 input-file2 ...
 

program.awkはどんなマルチラインプログラムでもかまいません。

# file print_fields.awk
BEGIN {print "this is a header"; FS=":"}
{print $1, $2}
END {print "that was it"}
 

そしてそれを実行してください:

awk -f print_fields.awk /etc/passwd   #-f advises awk which program file to load
 

またはより一般的には:

awk -f program-file input-file1 input-file2 ...
 

プログラムを別々のファイルに置くことの利点は、意味のある正しいIDでプログラムを書くことができること、#などのコメントを含めることができることです