文本处理工具awk+sed+grep

  1、awk:pattern scanning and processing language

  1)基本格式:awk 'pattern1{action1} pattern2{action2}...' filename,满足patternk则相应地执行actionk。其中,两种特殊的pattern分别是BEGIN和END。BEGIN后面的action在所有输入读入前执行,END之后的action在所有输入读入后执行。例子:

  统计第一列的总和:cat testfile | awk 'BEGIN {sum=0} {sum+=$1}END{print sum}'。

  列出UID小于10的用户名:cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1}'。和cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1}'的输出作比较,可以发现BEGIN在此处的作用(读入第一行时分隔符还是默认的空格或Tab,FS=":"在第二行才开始生效)。

  2)常用选项:-F:指定字段分割符(默认为空格和tab),因为awk是把一行分成多个字段来处理;-v var=val:将val赋给awk变量var,val可以是shell变量(需要用双引号括起来,而不能是单引号)。例子:

  查看appadmin用户所使用的bash:cat /etc/passwd | grep appadmin | awk -F ":" '{print $7}'。另有,$0表示整行,$(NF-1)表示倒数第二个字段...

  batch=1; echo "1&2&3" | awk -F '&' -v avar="$batch" '{if($1==avar) print $0}'。引用awk变量不需要$符号。

  3)内建变量:NF:当前行的字段数;NR:当前行号;FS:字段分隔符。ORS:输出记录的分隔符,默认是换行符。OFS:输出字段的分隔符,默认是空格。例子:

  查看每行各有多少字段:cat testfile |awk '{print "line " NR " has " NF " fields" }'。

  打印各个字段(事先不知道字段数):echo "path=12324&page=3&area=1" | awk -F '&' '{for(i=1; i<=NF; i++) print $i}'。

  交换列的顺序并设置列分隔符为tab:cat b|awk '{OFS="\t"}{print $2, $1}'。

  指定输出分隔符:echo "192.168.1.1|Firefox|www.google.com" | awk -F '|' 'BEGIN{ORS="\t"}{for(i=1;i<=NF;i++){if(i==NF)ORS="\n"; print $i;} }'。这种情况下,也可以用echo "192.168.1.1|Firefox|www.google.com" | awk -F '|' '{for(i=1;i<=NF;i++){if(i==NF)print $i; else printf $i"\t"}}',并且只有后者适用于多行文本。

  4)内置函数(使用某些函数可能需要安装gawk,否则会提示function and never defined之类的错误):

  (1)字符串函数:

  substr(s, i [, n]):返回从下标i开始的至多n个字符的子串。如echo abcde | awk '{res=substr($0, 1, 4); print res;}'的输出为abcd。

  strtonum(str):返回str的数值。若str以0开头,则假定它是八进制的;若str以0x/0X开头,则假定它是十六进制的;否则,假定它是十进制的。如echo "da" | awk '{print strtonum("0x"$1)}'的结果为218。

  (2)位操作函数:

  and(v1, v2)返回v1和v2位与的结果。

 

  2、sed:stream editor(流编辑器)。
  1)语法:sed option 'script' file1 file2...,或者sed option -f scriptfile file1 file2...
  2)常用选项(option):-f:指定sed脚本;-i:(仅当使用该选项时)直接修改文件,不能用于管道;-n:不默认输出模式空间的内容(见下例);-r:使用扩展的正规表达式(括号不必转义)。
  3)脚本(script):
  形式(1):/pattern/action,即对匹配pattern的行执行action。

  形式(2):[n1[,n2]]action,对n1~n2行执行action。$表示最后一行。

  这里需要先理解模式空间(pattern space,ps)和保留空间(hold space,hs)。模式空间ps初始内容为当前处理行,而保留空间hs初始内容为空行。常用的action:

  d:删除ps的内容,并开始下一轮(行)处理;p:打印当前ps的内容(默认也会打印当前ps的内容);x:交换hs和ps的内容;h/H:将ps的内容复制/追加到hs;g/G:将hs的内容复制/追加到ps;n/N:将下一行输入内容读入/追加到ps;s:对与正则表达式匹配的ps的内容进行替换操作;a:新增行;c:取代行;i:插入行。例子:

  > cat test
  hello world
  hell world
  hel world
  he world

  > sed '/hell world/{x;p;x;p}' test
  # 解析:"/hell world"只匹配到第二行,其它行按默认输出。
  # 解析:执行第一个x后,ps与hs的内容分别为空行和"hell world";执行p打印ps,即空行;
  # 解析:执行第二个x后,ps与hs的内容分别为"hell world"和空行;执行p打印ps,即"hell world"。
  hello world    # 这是默认输出。加-n选项后不会输出,下同。
  # 空行。p的输出
  hell world    # p的输出
  hell world    # 默认输出
  hel world    # 默认输出
  he world    # 默认输出

  > sed '/hell world/{x;p}' test    # 对匹配行执行{x;p}组合
  hello world    # 默认输出
  # 空行。p的输出
  # 空行。默认输出
  hel world    # 默认输出
  he world    # 默认输出

  > sed '/hell/d;G' test    # 对每行应用"/hell/d"和"G"两个script
  # 解析:注意d会立即开始下一轮处理,所以匹配行(第1、2行)不会执行G。
  hel world    # 默认输出
  # 空行。这是G的效果:首先把hs(空行)的内容追加到ps,再默认输出ps的内容。
  he world    # 默认输出
  # 空行。G的效果

  > sed 'n;G' test    # 在偶数行之后插入空行。每三行之后加一空行:sed 'n;n;G' test
  hello world
  hell world
  # 空行
  hel world
  he world
  # 空行

  > sed 'n;d' test    # 删除偶数行
  hello world
  hel world

  > sed = test | sed 'N;s/\n/     /'    # N的作用是加上行号,用于格式化输出。类似于nl命令

  1     hello world
  2     hell world
  3     hel world
  4     he world

  > sed -i 's/h/H/g' test    # 将所有行的h替换为H
  # 解析:这里空的pattern匹配所有行,g表示将匹配行的所有(而不是第一个)h替换成H。

  > sed 's/bc/-&-/' test    # 将所有行的第一个abc替换成a-bc-。&表示当前行中被匹配到的字符串。

  > sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/' test
  # 解析:将所有行的第一个324替换成-3-~2~4。"\1"和"\2"分别表示与第一、二个括号匹配到的内容。

  > echo "<body>Hello World</body>" | sed  's/<[^>]*>//g'    # 去掉所有HTML标签

  > cat test | sed '2a drink tea'    # 在第二行后增加新行

  > cat test | sed '2a NEW LINE 1 \    # 按回车键
  > NEW LINE 2'    # 承接上行。在第二行后增加2行

  > cat test | sed -e '4d' -e '2c NEW SECOND LINE'    # 使用-e连接两个及以上的script

 

  3、grep: print lines matching a pattern.

  1)常用选项:-x:“全行”匹配;-w:全词匹配;--exclude=GLOB:跳过名字和GLOB(通配符)匹配的文件;--include=GLOB:与exclude相反。只搜寻名字与GLOB(通配符)匹配的文件,如grep --include="*.cpp" --include="*.sh" "for" -wR *会递归地搜寻所有出现"for"的.cpp和.sh文件;-o, --only-matching:仅打印匹配到的字符串(非空),一行一个。-o可用于统计字符串的出现次数,如统计以下test.txt中hello出现的次数:grep -ow hello test.txt |wc -l

hello hellow hello
hello hello
hello helloh hello hello

 

 

 

 

不断学习中。。。

posted on 2013-10-11 20:04  han'er  阅读(449)  评论(0编辑  收藏  举报

导航