从初学awk到现在小有所成,非常感谢CUers的帮助,总结了下自己曾经遇到的问题和犯的错误,供初学者借鉴,因本人非计算机专业,对专业词汇可能有表述不对的地方,还请指正和补充!

1. awk ‘{code}1’ 中的“1”是干什么的?

一个完整的awk语句为:Awk ‘[patten]{action}……’, 其中pattern缺省为1,action缺省为{print}。

那么awk ‘1’完整的写法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的写法也是awk ‘1{print}’。

2. NR和FNR的区别是啥?

NR: 当前行记录数。

FNR: 当前文件的行记录数。

当awk处理的文件数超过1时,NR和FNR才会有区别。例如:

点击(此处)折叠或打开

  1. 1.cat file
  2. 2.a
  3. 3.b
  4. 4.c
  5. 5.d
  6. 6.e
  7. 7.f
  8. 8.
  9. 9.awk '{print "NR = " NR "  FNR = " FNR, $0}' file
  10. 10.NR = 1  FNR = 1 a
  11. 11.NR = 2  FNR = 2 b
  12. 12.NR = 3  FNR = 3 c
  13. 13.NR = 4  FNR = 4 d
  14. 14.NR = 5  FNR = 5 e
  15. 15.NR = 6  FNR = 6 f
  16. 16.
  17. 17.awk '{print "NR = " NR "  FNR = " FNR, $0}' file file
  18. 18.NR = 1  FNR = 1 a
  19. 19.NR = 2  FNR = 2 b
  20. 20.NR = 3  FNR = 3 c
  21. 21.NR = 4  FNR = 4 d
  22. 22.NR = 5  FNR = 5 e
  23. 23.NR = 6  FNR = 6 f
  24. 24.NR = 7  FNR = 1 a
  25. 25.NR = 8  FNR = 2 b
  26. 26.NR = 9  FNR = 3 c
  27. 27.NR = 10  FNR = 4 d
  28. 28.NR = 11  FNR = 5 e
  29. 29.NR = 12  FNR = 6 f

3. Awk怎么引入变量?

有两种方法:

(1): awk -v var=$VAR '{code}'

  (2): awk '{CODE}'$VAR'{CODE}'

  例如:

点击(此处)折叠或打开

  1. 1.VAR=XXX
  2. 2.
  3. 3.awk -v var=$VAR 'BEGIN{print var}'
  4. 4.XXX
  5. 5.
  6. 6.awk 'BEGIN{print "'$VAR'"}'
  7. 7.XXX

我推荐使用第一种方法,这样可以避免一些不必要的烦恼。如http://bbs.chinaunix.net/thread-1835620-1-1.html

4. 为什么OFS不起作用?

先看一个例子:

点击(此处)折叠或打开

  1. 1.echo 'aaa bbb ccc ddd
  2. 2.aaa bbb ccc ddd
  3. 3.aaa bbb ccc ddd
  4. 4.aaa bbb ccc ddd' |awk -v OFS="|" '{print $0}'
  5. 5.aaa bbb ccc ddd
  6. 6.aaa bbb ccc ddd
  7. 7.aaa bbb ccc ddd
  8. 8.aaa bbb ccc ddd

上面的例子中OFS为什么没有生效呢,原因是OFS指的是输出字段分隔符,所以必须对字段进行操作时OFS才会起作用,正确的方法应该是:

点击(此处)折叠或打开

  1. 1.echo 'aaa bbb ccc ddd
  2. 2.aaa bbb ccc ddd
  3. 3.aaa bbb ccc ddd
  4. 4.aaa bbb ccc ddd' |awk -v OFS="|" '{$1=$1;print $0}'
  5. 5.aaa|bbb|ccc|ddd
  6. 6.aaa|bbb|ccc|ddd
  7. 7.aaa|bbb|ccc|ddd
  8. 8.aaa|bbb|ccc|ddd

正如Tim大师所讲的,$1=$1这个action,是我们对awk撒的谎,目的就是为了使得OFS生效,除此之外,NF+=0也是常用的方法。参考:http://bbs.chinaunix.net/viewthr ... p;extra=&page=1

5. 同样的代码,别人运行成功,为什么我运行失败?

这个问题的原因很多,我这里列举两个最常见的,大家可以补充。

<1>: awk版本引起的,如gawk中的一些扩展函数或变量,在nawk中没有,或是不同版本的(g/n)awk也会有差别,这样情况需要重新编写。

<2>: 文本格式的问题,cat-A file查看一下,如果是,dos2unix应该可以解决。

注:书写错误也有可能哦.

6. Awk 语句中可以使用{n,m}这样的正则么?

可以,使用方法:gawk -- re-interval ,其它版本使用方法会有所不同,请大家补充

7. BEGIN 和END 到底是怎么一回事?

有时,对于新手可能也会是个问题。简单说下:

BEGIN {action} : 读取文本之前进行的操作。要避免类似下面的写法:

点击(此处)折叠或打开

  1. 1.awk 'BEGIN{ filename =  FILENAME}' file
  2. 2.# or:
  3. 3.awk 'BEGIN{FS=":"; for(i=2;i<=NF;i++) print $i}' file

如果BEGIN 模块中使用getline函数时,情况会有所不同:

点击(此处)折叠或打开

  1. 1.cat file
  2. 2.1
  3. 3.2
  4. 4.3
  5. 5.4
  6. 6.5
  7. 7.
  8. 8.awk 'BEGIN{while (getline <"file") print}' file
  9. 9.1
  10. 10.2
  11. 11.3
  12. 12.4
  13. 13.5

END {action}: 

它在整个输入文件处理完成后被执行,同样无法对文本进行任何操作,如匹配某个pattern执行action。

8. print,printf 和sprintf?

print:为一般的打印

printf:可以定义打印格式

sprintf:可以完成和printf相同的功能,不同的是sprintf只能输出值,并不能完成打印的功能。

print默认有个换行\n,而printf没有,当然它和C语言的printf类似(awk本是c的近亲),能打印各种格式,但默认没有换行。

例如:

点击(此处)折叠或打开

  1. 1.awk 'BEGIN{var=123; print "var = " var}'
  2. 2.var = 123
  3. 3.
  4. 4.awk 'BEGIN{var=123;printf "%s %5f\n", "var =",var}'
  5. 5.var = 123.000000
  6. 6.
  7. 7.awk 'BEGIN{var=123;sprintf ("%s  %5f\n", "var =",var)}'
  8. 8.
  9. 9.
  10. 10.awk ‘BEGIN{var1=123;var2=sprintf ("%5f",var1); print "var2 =" var2}’
  11. 11.var2 = 123.000000

9. “a==b?c:d” ?

这个是一个if语句的简写,即conditional expression1 ? expression2: expression3;完整写法为:

if(a==b) {c} else {d}

10. awk ‘! a[$0]++’ 怎么理解?

这是一个非常经典的去重复项的awk语句,虽然短小,不过涉及到了不少知识点,下面一一解读:

<1> :”!” 即非。

<2>:a[$0],以$0为数据下标,建立数组a

<3>:a[$0]++,即给数组a赋值,a[$0]+=1

<4> :那么组合起来,awk是怎么执行!a[$0]++的呢?我用一个实际例子来解释:

点击(此处)折叠或打开

  1. 1.cat file
  2. 2.111
  3. 3.222
  4. 4.111
  5. 5.222
  6. 6.333
  7. 7.
  8. 8.awk '{print a[$0],!a[$0]++,a[$0],!a[$0],$0}' file
  9. 9.  1 1 0 111
  10. 10.  1 1 0 222
  11. 11.1 0 2 0 111
  12. 12.1 0 2 0 222
  13. 13.  1 1 0 333

原来,第一个a[$0]的值为空,所以!a[$0]++是先作判断,结果为1(非空为真,即为1),再作数组赋值a[$0]++。这也就是为什么前面的!a[$0]++并不一定等于后面的!a[$0]。

awk ‘++a[$0]==1’ 和上面的代码作用一样,你理解了么?

11. 如何打印单双引号?

点击(此处)折叠或打开

  1. 1.awk 'BEGIN {print "single quote --> '\''";print "double quote --> \"" }'
  2. 2.single quote --> '
  3. 3.double quote --> "

更可靠的的方法如Tim所示:

点击(此处)折叠或打开

  1. 1.awk 'BEGIN {print "single quote --> \047";print "double quote --> \042" }'

12. awk 语句中多个{}是怎么执行的?

还是用个例子来说明:

点击(此处)折叠或打开

  1. 1.cat file
  2. 2.1
  3. 3.2
  4. 4.3
  5. 5.4
  6. 6.5
  7. 7.
  8. 8.awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 这个语句中包含三个action
  9. 9.@@ 11   # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
  10. 10.@@ 22   # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
  11. 11.|| 3 @@ 33  # 判断$1==3?是,执行{print “|| “$0}; 执行 action {printf " @@ "$0};执行 action {print $0}
  12. 12.@@ 44  # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
  13. 13.@@ 55  # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

这样可以清楚的看出,awk是一行一行读取文本,然后按照代码的前后顺序执行。但如果action中包含next或exit时,有所不同:

点击(此处)折叠或打开

  1. 1.awk '$1==3{printf "|| "$0;next}{printf "@@ "$0}{print $0}' file
  2. 2.@@ 11
  3. 3.@@ 22
  4. 4.|| 3@@ 44
  5. 5.@@ 55
  6. 6.
  7. 7.awk '$1==3{printf "|| "$0;exit}{printf "@@ "$0}{print $0}' file
  8. 8.@@ 11
  9. 9.@@ 22
  10. 10.|| 3

13. FS, OFS, RS, ORS?

最后用图解的方式说明一下这四个变量:





14.Awk 内置的字符串函数

gsub(r,s)

在整个$0中用s代替r

gsub(r,s,t)

在整个t中用s替代r

index(s,t)

返回s中字符串t的第一位置

length(s)

返回s长度

match(s,r)

测试s是否包含匹配r的字符串

split(s,a,fs)

在fs上将s分成序列a

sprint(fmt,exp)

返回经fmt格式化后的exp

sub(r,s)

用$0中最左边最长的子串代替s

substr(s,p)

返回字符串s中从p开始的后缀部分

substr(s,p,n)

返回字符串s中从p开始长度为n的后缀部分

gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。

index(s,t)函数返回目标字符串s中查询字符串t的首位置。length函数返回字符串s字符长度。

match函数测试字符串s是否包含一个正则表达式r定义的匹配。

split使用域分隔符fs将字符串s划分为指定序列a。

sprint函数类似于printf函数,返回基本输出格式fmt的结果字符串exp。

sub(r,s)函数将用s替代$0中最左边最长的子串,该子串被r匹配。

substr(s,p)返回字符串s在位置p后的后缀。

substr(s,p,n)同上,并指定子串长度为n。

此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。

awk中的gsub的&,表示要被替换的原始字符。gsub(/[0-9]+/,”\\0x&”),这时&表示[0-9]所匹配到的字符。

15.awk常见错误检查

当第一次使用awk时,可能被错误信息搅得不知所措,但通过长时间和不断的学习,可总

结出以下规则。在碰到 awk错误时,可相应查找:

? 确保整个awk命令用单引号括起来。

? 确保命令内所有引号成对出现。

? 确保用花括号括起动作语句,用圆括号括起条件语句。

? 可能忘记使用花括号,也许你认为没有必要,但 awk不这样认为,将按之解释语法。

?正则表达式用斜线括起来!      \ ^ $ . [] | () * + ?





ARGC:支持命令行中传入 a w k脚本的参数个数。

ARGV:是ARGC的参数排列数组,其中每一元素表示为ARGV[n], n为期望访问的命令行参数。

ENVIRON :支持系统设置的环境变量,要访问单独变量,使用实际变量名,例如

ENVIRON [“ EDITOR”] =“Vi”。

FILENAME:支持awk脚本实际操作的输入文件。

因为awk可以同时处理许多文件,因此如果访问了这个变量,将告之系统目前正在浏览的实际文件。

FNR:支持awk目前操作的记录数。其变量值小于等于 NR。如果脚本正在访问许多文件,

每一新输入文件都将重新设置此变量。

FS:用来在awk中设置域分隔符,与命令行中 - F选项功能相同。缺省情况下为空格。

如果用逗号来作域分隔符,设置 FS = ","。

NF:支持记录域个数,在记录被读之后再设置。

OFS:允许指定输出域分隔符,缺省为空格。如果想设置为 #,写入OFS = "#"。

ORS:为输出记录分隔符,缺省为新行(\n)。

RS:是记录分隔符,缺省为新行 (\n)。

16.awk操作符

域值比较操作

有两种方式测试一数值域是否小于另一数值域。

1) 在BEGIN中给变量名赋值。

2) 在关系操作中使用实际数值。

通常在BEGIN部分赋值是很有益的,可以在awk表达式进行改动时减少很多麻烦。

使用关系操作必须用圆括号括起来。

AWK内置字符串函数

从shell中向awk传入字符串

(1) 使用管道将字符串stand-by传入awk,返回其长度。

(2) 设置文件名为一变量,管道输出到awk,返回不带扩展名的文件名。

(3) 设置文件名为一变量,管道输出到awk,只返回其扩展名。

字符串屏蔽序列

printf修饰符

向一行awk命令传值

在查看awk脚本前,先来查看怎样在 awk命令行中传递变量。

在awk执行前将值传入awk变量,需要将变量放在命令行中,格式如下:

awk 命令变量=输入文件值

在awk中使用F S变量

使用awk脚本时,记住设置 FS变量是在 BEGIN部分。

向awk脚本传值

格式:awk script_file var=value input_file

awk数组

数组使用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是

一种循环类型的基本结构:for (element in array )  print array[element]

[SHELL]awk的用法举例的更多相关文章

  1. 【转】awk 里的substr函数用法举例

    awk 里的substr函数用法举例: 要截取的内容:2007-08-04 04:45:03.084 - SuccessfulTradeResult(status: 1, currencyPair: ...

  2. Linux sed 和 awk的用法

    sed用法: 原文链接:http://www.cnblogs.com/dong008259/archive/2011/12/07/2279897.html sed是一个很好的文件处理工具,本身是一个管 ...

  3. <三剑客> 老大:awk命令用法

    awk是一种编程语言,用于在linux/unix下对文本和数据进行处理.数据可以来自标准输入(stdin).一 个或多个文件,或其它命令的输出.它支持用户自定义函数和动态正则表达式等先进功能,是lin ...

  4. awk命令_Linux awk 命令用法详解

    本文索引 awk命令格式和选项 awk模式和操作 模式 操作 awk脚本基本结构 awk的工作原理 awk内置变量(预定义变量) 将外部变量值传递给awk awk运算与判断 算术运算符 赋值运算符 逻 ...

  5. sed的实际用法举例

    sed:Stream Editor文本流编辑,sed是一个“非交互式的”面向字符流的编辑器.能同时处理多个文件多行的内容,可以不对原文件改动,把整个文件输入到屏幕,可以把只匹配到模式的内容输入到屏幕上 ...

  6. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

  7. c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例

    c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...

  8. Shell expr的用法 bc 命令 let命令

    Shell expr的用法  bc 命令   let命令 数学运算 let命令  expr命令  bc命令  $(())   $[] http://www.80ops.cn/archives/245. ...

  9. hbase基本概念和hbase shell常用命令用法

    1. 简介 HBase是一个分布式的.面向列的开源数据库,源于google的一篇论文<bigtable:一个结构化数据的分布式存储系统>.HBase是Google Bigtable的开源实 ...

随机推荐

  1. div 四周都有阴影的写法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. word-wrap与word-break为长单词换行

    如果你遇到长串英文单词或者url换行的问题,这时候就需要用到word-wrap与word-break这2个css属性啦. word-wrap:break-word;长单词与url地址自动换行. wor ...

  3. javascript回调函数那些事~

    什么是回调函数? 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直 ...

  4. AJPFX总结string类和简单问题

    String表示字符串,所谓字符串,就是一连串的字符;String是不可变类,一旦String对象被创建,包含在对象中的字符序列(内容)是不可变的,直到对象被销毁://一个String对象的内容不能变 ...

  5. ubuntu安装mysql多实例

    想要尝试mysql的读写分离,在云上安装完mysql之后突然想到一个问题:我本机是没有公网IP的. 开始尝试在唯一一台云服务器上安装多个mysql实例. 主要步骤: 1.新建MySQL目录 (1):新 ...

  6. java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()

    原因:hibernate-jpa-2.0-api-1.0.0.Final.jar.ejb3-persistence.jar中的javax.persistence与javaEE 5 Librares中的 ...

  7. Using URL Schemes to Communicate with Apps

    要素:1)通信双方:2)协议:3)支持机制(系统,进行协议注册):4)数据 https://developer.apple.com/library/content/documentation/iPho ...

  8. Java之流水号生成器实现

    参考:https://www.jianshu.com/p/331b872e9c8f 1.建立一张存放的表 CREATE TABLE `sys_serial_number` ( `id` bigint( ...

  9. 前端什么是BFC

    什么是BFC? 全称块级格式化上下文?什么意思不懂.看了好多博客,基本都是抄的,真心都不是大白话.我今天来总结一下,用菜鸟级别的语言来描述. BFC 应该可以抽象成一个 独立的个体,出淤泥而不染的白莲 ...

  10. find、filter、map的区别

    1.find 查询数组中符合条件的第一个元素,如果没有符合条件的元素则返回空数组 ,,,,,,] ) var men=[ {name:',sex:'女'}, {name:',sex:'nan'}, { ...