awkawk入门


备注

AWK的名字来自其创作者Alfred V. Aho,Peter J. Weinberger和
Brian W. Kernighan。

资源

版本

名称初始版本发布日期
POSIX awk 1992年 IEEE Std 1003.1,2013 Edition 2013年4月19日
一个真Awk或nawk或BWK awk 198X - 二○一二年十二月二十〇日
GNU awk或gawk 1986年 4.1.3 2015年5月19日

AWK通过例子

AWK是字符串操作语言,主要用于UNIX系统。 AWK背后的想法是创建一种在处理文件时使用的通用语言,这种语言并不太复杂,无法理解。

AWK还有其他一些变体,但主要概念是相同的,只是附加功能。这些其他变体是NAWK和GAWK。 GAWK包含两者的所有功能,如果您愿意,NAWK比AWK高出一步。

想到AWK最简单的方法是考虑它有两个主要部分。模式和行动。

可能是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列。

因此,此示例将打印:文件作者位于顶行,而第二行则处理文件路径。 $ 8是文件的名称,$ 3是所有者(当查看目录路径时,这将更加清晰)。最后,底线将打印,如您所料 - 完成 -

以上示例的信用转到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单行:

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> 条件通常是正则表达式/re/ ,与awk输入行匹配;
  • <* actions>语句序列,类似于shell命令,配有类似C的结构。

``按照以下规则处理:
  1. BEGIN ...END ... 是可选的,在处理awk输入行之前或之后执行。
  2. 对于awk输入中的每一行,如果condition <condN> 为meat,则执行相关的<program actions> 块。
  3. {<program actions>} 默认为{print $0}

条件可以与标准逻辑运算符组合:

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

其中&& 优先于|| ;

print 声明print item1 item2 语句在STDOUT上打印项目。
项可以是变量( X$0 ),字符串(“hello”)或数字。
item1, item2OFS 变量的值进行整理;
item1 item2 只是justapoxed !使用item1 " " item2 表示空格或printf表示更多功能。

变量不需要$ ,即: 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}'
 

打印第二个字段匹配正则表达式/ re /的第三和第四个字段。

一些字符串函数

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]) 返回的位置s 其中正则表达式r 发生并设定的值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-like是构造语句:

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

用于打印可变长度描述元素的C样式循环,从字段4开始:

# 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}
...
 

传递shell变量

# 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: 我们建议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 ...
 

将程序放在一个单独的文件中的优点是你可以编写具有正确标识的程序来理解,你可以用#等包含注释