awk 和cut命令

时间:2024.4.20

linux命令之sed, awk, grep, cut篇

用下来感觉这4个命令比较常用,功能也比较强大,等我有时间了要好好整理一下。

首先介绍一下cut,之前有文章已经讲过它的用法了,这次连带cut的死对头paste,一起拎出来讲讲。

第一篇 cut

常用参数:

-c 根据字符,用法:cut -cnum1-num2 filename 截取num1~num2之间的字符,字符从1开始记。

-f 根据域,默认为tab分隔

-d 定义域分隔符

范例:

shell> cat example

test2

this is test1

shell> cut -c1-6 example ## print 开头算起前 6 个字元

test2

this i

-c m-n 表示显示每一行的第m个字元到第n个字元。例如:

---------file-----------

liubi 23 14000

---------file-----------

# cut -c 1-5,10-14 file

liubi 14000

-f m-n 表示显示第m栏到第n栏(使用tab分隔)。例如:

---------file-----------

liubi 23 14000

---------file-----------

# cut -f 1,3 file

liubi 14000

-c 和 -f 参数可以跟以下子参数:

m 第m个字符或字段

m- 从第m个字符或字段到文件结束

m-n 从第m个到第n个字符或字段

-n 从第1个到第n个字符或字段

我们经常会遇到需要取出分字段的文件的某些特定字段,例如 /etc/password就是通过":"分隔各个字段的。可以通过cut命令来实现。例如,我们希望将系统账号名保存到

特定的文件,就可以:

cut -d: -f 1 /etc/passwd > /tmp/users

-d用来定义分隔符,默认为tab键,-f表示需要取得哪个字段

如:

使用|分隔

cut -d'|' -f2 1.test>2.test

使用:分隔

cut -d':' -f2 1.test>2.test

这里使用单引号或双引号皆可。

对于特殊字符用\来转义(以“-”为分隔符切割后,要第一个字段): BGIOSGA005099-TA

BGIOSGA005310-TA

cut -d\- -f 1 file >out

或者:cut "\-" -f 1 file >out

cut的死对头:paste

paste file1 file2 >file3

把文件1与文件2按列合并(有没有发现跟cut正好相反呢?)

$ less 111

abc ddd eee

$ less 222

123 444 555

$ paste 111 222 >333

$ less 333

abc ddd eee 123 444 555

用-d参数可以自定义分隔符

$ paste -d: 111 222 >444

$ less 444

abc ddd eee:123 444 555

paste命令还有一个很有用的选项"-"。意即对每一个"-",从标准输入中读一次数据。-d参数来定义分隔符。以一个3列格式显示目录列表。方法如下: $ ls |paste -d: - - - #注意,"-"和"-"之间有空格

block_info_down_1000:block_info_down_3000:sv_test

block_info_up1000:block_info_up3000:module_indel_sv

module_test:old:regulation_region_down.pl

sample.Q20.down1000:sample.Q20.down3000:sample.Q20.up1000

sample.Q20.up3000:sample_to_9311.snp.Q20.filter.sort:sample_to_test 第二篇 awk

awk 用法:awk ' pattern {action} '

变量名 含义

ARGC 命令行变元个数

ARGV 命令行变元数组

FILENAME 当前输入文件名

FNR 当前文件中的记录号

FS 输入域分隔符,默认为一个空格

RS 输入记录分隔符

NF 当前记录里域个数

NR 到目前为止记录数

OFS 输出域分隔符

ORS 输出记录分隔符

用法介绍:

1,模式匹配

awk '/zqy/' fileA #寻找出fileA中含有zqy的行 等同于awk '$0~/zqy/' fileA awk '$1~/88/' fileA #找出第一个域里面包含88的行

awk '$1~/88/{print $2}' fileA #找出第一个域里面包含88的行后,只打印该行的第二个域

2,对不同的域进行操作

awk '$2 >25 && $2<=55' fileA #找出第二个域里面满足条件的行,可以加上{print $n}来打印任意域

############### fileB #################

884 46 1 8 5 944

734 41 0 10 2 787

647 29 1 8 1 686

536 26 1 9 0 572

############### fileB #################

$ less fileB

884 46 1 8 5 944

734 41 0 10 2 787

647 29 1 8 1 686

536 26 1 9 0 572

$awk '{print NR,NF,$NF}' fileB # NR:文件当前记录号(在这里可以理解为行数); NF:总的域的个数(可以理解为列数); $NF:想一想是什么东西吧?再不知道就撞墙去吧。

1 6 944

2 6 787

3 6 686

4 6 572

3,通过-F参数来改变域分隔符,FS设置输入分隔符,OFS设置输出分隔符,awk所有操作都支持管道。如:

df | awk '$4>1000000 ' 通过管道符获得输入,如:显示第4个域满足条件的行。

awk -F "|" '{print $1}' file 按照新的分隔符“|”进行操作。

awk 'BEGIN { FS="[: \t|]"}{print $1,$2,$3}' file 通过设置输入分隔符(FS="[: \t|]")修改输入分隔符。BEGIN 表示在处理任意行之前进行的操作。 awk 'BEGIN { OFS="%"} {print $1,$2,$3}' file 通过设置输出分隔符(OFS="%")修改输出格式。

Sep="|"

awk -F $Sep '{print $1}' file 按照环境变量Sep的值做为分隔符。 awk -F '[ :\t|]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。

awk -F '[][]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表

[、]

4、

awk -f awkfile file 通过文件awkfile的内容依次进行控制。

cat awkfile

/101/{print "\047 Hello! \047"} --遇到匹配行以后打印 ' Hello! '.\047代表单引号。

{print $1,$2} --因为没有模式控制,打印每一行的前两个域。

5、

awk 'BEGIN { max=100 ;print "max=" max} {max=($1 >max ?$1:max); print $1,"Now max is "max}' file 取得文件第一个域的最大值。

awk '{print ($1>4 ? "high "$1: "low "$1)}' file

6、

awk '{$1 == 'Chi' {$3 = 'China'; print}' file 找到匹配行后先将第3个域替换后再显示该行(记录)。

awk '{$7 %= 3; print $7}' file 将第7域被3除,并将余数赋给第7域再打印。

7、

awk '/tom/ {wage=$2+$3; printf wage}' file 找到匹配行后为变量wage赋值并打印该变量。

8、

awk '/tom/ {count++;} END {print "tom was found "count" times"}' file #END表示在所有输入行处理完后进行处理。

9、awk 'gsub(/\$/,"");gsub(/,/,""); cost+=$4;END {print "The total is $" cost>"filename"}' file gsub函数用空串替换$和,再将结果输出到filename中。

1 2 3 $1,200.00

1 2 3 $2,300.00

1 2 3 $4,000.00

awk '{gsub(/\$/,"");gsub(/,/,"");

if ($4>1000&&$4<2000) c1+=$4;

else if ($4>2000&&$4<3000) c2+=$4;

else if ($4>3000&&$4<4000) c3+=$4;

else c4+=$4; }

END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file

通过if和else if完成条件语句

awk '{gsub(/\$/,"");gsub(/,/,"");

if ($4>3000&&$4<4000) exit;

else c4+=$4; }

END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file

通过exit在某条件时退出,但是仍执行END操作。

awk '{gsub(/\$/,"");gsub(/,/,"");

if ($4>3000) next;

else c4+=$4; }

END {printf "c4=[%d]\n",c4}"' file

通过next在某条件时跳过该行,对下一行执行操作。

10、awk '{ print FILENAME,$0 }' file1 file2 file3>fileall 把file1、file2、file3的文件内容全部写到fileall中,并前置文件名。

11、awk ' $1!=previous { close(previous); previous=$1 } {print substr($0,index($0," ") +1)>$1}' fileall 把合并后的文件重新分拆为3个文件。并与原文件一致。

12、awk 'BEGIN {"date"|getline d; print d}' 通过管道把date的执行结果送给getline,并赋给变量d,然后打印。

13、awk 'BEGIN {system("echo \"Input your name:\\c\""); getline d;print "\nYour name is",d,"\b!\n"}'

通过getline命令交互输入name,并显示出来。

awk 'BEGIN {FS=":"; while(getline< "/etc/passwd" >0) { if($1~"050[0-9]_") print $1}}'

打印/etc/passwd文件中用户名包含050x_的用户名。

14、awk '{ i=1;while(i<NF) {print NF,$i;i++}}' file 通过while语句实现循环。

awk '{ for(i=1;i<NF;i++) {print NF,$i}}' file 通过for语句实现循环。

type file|awk -F "/" '

{ for(i=1;i<NF;i++)

{ if(i==NF-1) { printf "%s",$i }

else { printf "%s/",$i } }}' 显示一个文件的全路径。 用for和if显示日期

awk 'BEGIN {

for(j=1;j<=12;j++)

{ flag=0;

printf "\n%d月份\n",j;

for(i=1;i<=31;i++)

{

if (j==2&&i>28) flag=1;

if ((j==4||j==6||j==9||j==11)&&i>30) flag=1;

if (flag==0) {printf "%02d%02d ",j,i}

}

}

}'

15、在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串 Flag=abcd

awk '{print '$Flag'}' 结果为abcd

awk '{print "$Flag"}' 结果为$Flag

一、sort

Usage: sort [OPTION]... [FILE]...

-o 输出文件

-d 按字典顺序排序

-n 按数据大小输出

-r 按逆序输出排序结果

-k 指定分类是域上的数字分类

-t 域分隔符,用非空格或tab分隔域

sort -k3 -n -r -t: /etc/passwd

sort -d /etc/passwd

二、WC

Usage: wc [OPTION]... [FILE]...

-c 字符数量~

-l 行数~

-w 统计单词数量~

wc /etc/passwd

36 65 1739 /etc/passwd #36行,65个单词(空格区分),1739个字符

三、diff

diff

Usage: diff [OPTION]... FILES

Compare files line by line.

-q 显示有无差异,不显示详细的信息~

-c 显示全部内文,并标出不同之处~

-b 不检查空格字符的不同~

-B 不检查空白行

-r 比较子目录中的文件~

diff /etc/passwd ./passwd.bak

2d1

< bin:x:1:1:bin:/bin:/sbin/nologin

四、grep

Usage: grep [OPTION]... PATTERN [FILE] ...

Search for PATTERN in each FILE or standard input.

-c 只打印匹配的行编号数

-i 匹配文本时忽略大小写

-n 在每行前显示其行编号

-v 逆向输出,打印不匹配的行

-f file 要匹配的字符在文件列表中

cat /etc/passwd |grep -n root

1:root:x:0:0:root:/root:/bin/bash

12:operator:x:11:0:operator:/root:/sbin/nologin

#grep '[Tt]his' file.txt

#grep '^[^#]' file.txt

匹配任意字符

grep 'r..t' /etc/passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

五、sed

sed

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... S 替代操作

i 插入命令

a 附加命令

d 删除全部匹配行

D 删除首次匹配的行

#sed -n '1,4p' /etc/passwd 打印1~4行,-n --quiet以免先打印出passwd的全部内容

#sed '/80/D' file.txt

#sed 's/var/usr/g' file.txt 替换file.txt中全部var为usr

#sed '50,$s/help/man/g' file.txt 从50~最后行替换help为man

sed '/done/d' xj_user_p.log 删除done

六、awk

Usage: awk [POSIX or GNU style options] -f progfile [--] file ... Usage: awk [POSIX or GNU style options] [--] 'program' file ... gawk '{ sum += $1 }; END { print sum }' file

gawk -F: '{ print $1 }' /etc/passwd

NF 当前记录中的字段数。NR 当前记录数。

awk -F: '{print NR,$1,$NF}' ./passwd.bak

awk -F: 'NR%10==5{print NR,$0}' ./passwd.bak 打印出5,15,25...行 5 sync:x:5:0:sync:/sbin:/bin/sync

15 nobody:x:99:99:Nobody:/:/sbin/nologin

25 apache:x:48:48:Apache:/var/www:/sbin/nologin

七、uniq

如果要在文件中查找重复的行,uniq命令会很有用,该命令一般格式为:uniq in_file out_file

该格式中,uniq把in_file复制到out_file,处理过程中,去掉其中的重复行,uniq对重复行的定义是完全匹配的连续行。如果不指定out_file,结果就写入标准输出。

-d选项:它告诉uniq把文件中的重复行写入out_file,不管它们在文件中连续出现多少次,这样的连续行只写一次

-c选项:带-c选项后,每行最前面显示该行在输入文件中出现的次数。

$ more test.txt

aaa

ccc

ccc

ccc

ddd

bbb

eee

123

$ uniq test.txt

aaa

ccc

ddd

bbb

eee

123

$ uniq -d test.txt

ccc

$ uniq -c test.txt

1 aaa

3 ccc

1 ddd

1 bbb

1 eee

1 123

$

综合示例:

...

数据处理:

找出上海股票涨幅最大的股票?

sort -n -r -k4 t.txt | sed -n '1p' 涨幅>3的股票?

awk '{if ($1>3) print $0} ' t.txt 涨幅在在4~15之间的股票

awk '{if($4>0&&$4<15){print $0}}' t.txt

linux下grep命令用法实例教程 /linux/1008.html 一,grep命令有什么用

个人觉得grep命令就是一个对文本或输出进行匹配并控制输出的一个工具,看一下下面的参数,部分翻译了,有不对的地方,还请指正

grep --help

匹配模式选择:

-E, --extended-regexp 扩展正则表达式egrep

-F, --fixed-strings 一个换行符分隔的字符串的集合fgrep

-G, --basic-regexp 基本正则

-P, --perl-regexp 调用的perl正则

-e, --regexp=PATTERN 后面根正则模式,默认无

-f, --file=FILE 从文件中获得匹配模式

-i, --ignore-case 不区分大小写

-w, --word-regexp 匹配整个单词

-x, --line-regexp 匹配整行

-z, --null-data a data line ends in 0 byte, not newline

杂项:

-s, --no-messages 不显示错误信息

-v, --invert-match 显示不匹配的行

-V, --version 显示版本号

--help 显示帮助信息

--mmap use memory-mapped input if possible

输入控制:

-m, --max-count=NUM 匹配的最大数

-b, --byte-offset 打印匹配行前面打印该行所在的块号码。

-n, --line-number 显示的加上匹配所在的行号

--line-buffered 刷新输出每一行

-H, --with-filename 当搜索多个文件时,显示匹配文件名前缀

-h, --no-filename 当搜索多个文件时,不显示匹配文件名前缀

--label=LABEL print LABEL as filename for standard input

-o, --only-matching show only the part of a line matching PATTERN -q, --quiet, --silent 不显示任何东西

--binary-files=TYPE assume that binary files are TYPE

TYPE is 'binary', 'text', or 'without-match'

-a, --text 匹配二进制的东西

-I 不匹配二进制的东西

-d, --directories=ACTION 目录操作,读取,递归,跳过

ACTION is 'read', 'recurse', or 'skip'

-D, --devices=ACTION 设置对设备,FIFO,管道的操作,读取,跳过 ACTION is 'read' or 'skip'

-R, -r, --recursive 递归调用

--include=PATTERN files that match PATTERN will be examined

--exclude=PATTERN files that match PATTERN will be skipped.

--exclude-from=FILE files that match PATTERN in FILE will be skipped. -L, --files-without-match 匹配多个文件时,显示不匹配的文件名

-l, --files-with-matches 匹配多个文件时,显示匹配的文件名

-c, --count 显示匹配了多少次

-Z, --null print 0 byte after FILE name

文件控制:

-B, --before-context=NUM 打印匹配本身以及前面的几个行由NUM控制 -A, --after-context=NUM 打印匹配本身以及随后的几个行由NUM控制 -C, --context=NUM 打印匹配本身以及随后,前面的几个行由NUM控制 -NUM 根-C的用法一样的

--color[=WHEN],

--colour[=WHEN] use markers to distinguish the matching string WHEN may be `always', `never' or `auto'.

-U, --binary do not strip CR characters at EOL (MSDOS)

-u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS) 二,准备测试文件test

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa

DADddd:x:2:2:daemon:/sbin:/bin/false

mail:x:8:12:mail:/var/spool/mail:/bin/false

ftp:x:14:11:ftp:/home/ftp:/bin/false

&nobody:$:99:99:nobody:/:/bin/false

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

http:x:33:33::/srv/http:/bin/false

dbus:x:81:81:System message bus:/:/bin/false

hal:x:82:82:HAL daemon:/:/bin/false

mysql:x:89:89::/var/lib/mysql:/bin/false

aaa:x:1001:1001::/home/aaa:/bin/bash

ba:x:1002:1002::/home/zhangy:/bin/bash

test:x:1003:1003::/home/test:/bin/bash

@zhangying:*:1004:1004::/home/test:/bin/bash

policykit:x:102:1005:Po

这个测试文件,根介绍sed和awk命令时用的一样的,是个密码文件。

三,应用举例

[root@krlcgcms01 test]# grep root test

root:x:0:0:root:/root:/bin/bash

匹配含有root的行

查看复制打印?

[root@krlcgcms01 test]# cat test |grep '^\(root\|zhang\)'

root:x:0:0:root:/root:/bin/bash

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

匹配以root开头或者以zhang开头的行,注意反斜杠

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -e '^\(root\|zhang\)' root:x:0:0:root:/root:/bin/bash

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

匹配以root开头或者以zhang开头的行,注意反斜杠,根上面一个例子一样,-e默认是省去的

查看复制打印?

[root@krlcgcms01 test]# echo 'zhangying' |grep '^zhang[a-z]*$' zhangying

匹配以zhang开头,只含有字母

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -E '^bin'

bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa

匹配以bin开头的行,用的egrep,在这里可以换成-F,-G

[root@krlcgcms01 test]# cat test|grep -n zhangy

7:zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

13:ba:x:1002:1002::/home/zhangy:/bin/bash

15:@zhangying:*:1004:1004::/home/test:/bin/bash

在匹配的行前面加上该行在文件中,或者输出中所在的行号

[root@krlcgcms01 test]# cat test|grep -nv bin

16:policykit:x:102:1005:Po

不匹配以bin开头的行,并显示行号

[root@krlcgcms01 test]# cat test|grep -c zhang

3

显示匹配的个数,不显示内容

[root@krlcgcms01 test]# grep system test

[root@krlcgcms01 test]# grep -ni system test

9:dbus:x:81:81:System message bus:/:/bin/false

匹配system,没有加-i没有匹配到东西。

[root@krlcgcms01 test]# cat test|grep -w zhan

[root@krlcgcms01 test]# cat test|grep -w zhangy

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

ba:x:1002:1002::/home/zhangy:/bin/bash

匹配zhan没有匹配到东西,匹配zhangy能匹配到,因为在test文件中,有zhangy这个单词

查看复制打印?

[root@krlcgcms01 test]# echo "aaaaaa" |grep -x aaa

[root@krlcgcms01 test]# echo "aaaa" |grep -x aaaa

aaaa

在这里-x后面东西,和输出中的整行相同时,才会输出

[root@krlcgcms01 test]# cat test |grep -m 1 zhang

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

最多只匹配一次,如果把-m 1去掉的话,会有三个

[apacheuser@krlcgcms01 test]$ cat test |grep -b zha

241:zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

480:ba:x:1002:1002::/home/zhangy:/bin/bash

558:@zhangying:*:1004:1004::/home/test:/bin/bash

匹配行的前面显示块号,这个块号是干什么的,不知道,有谁知道可否告诉我一下

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep -H 'root' test test2 testbak test:root:x:0:0:root:/root:/bin/bash

test2:root

testbak:root:x:0:0:root:/root:/bin/bash

多文件匹配时,在匹配的行前面加上文件名

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep -h 'root' test test2 testbak root:x:0:0:root:/root:/bin/bash

root

root:x:0:0:root:/root:/bin/bash

多文件匹配时,在匹配的行前面不加上文件名

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep -l 'root' test test2 testbak DAta test

test2

testbak

多文件匹配时,显示匹配文件的文件名

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep -L 'root' test test2 testbak DAta DAta

多文件匹配时,在匹配的行前面不加上文件名

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep 'root' test

root:x:0:0:root:/root:/bin/bash

[apacheuser@krlcgcms01 test]$ grep -o 'root' test

root

root

root

没有-o时,有一行匹配,这一行里面有3个root,加上-o后,这个3个root就出来了

[apacheuser@krlcgcms01 test]$ grep -V

grep (GNU grep) 2.5.1

Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.

显示版本

查看复制打印?

[apacheuser@krlcgcms01 test]$ grep -q 'root' test

不显示任何内容

[root@krlcgcms01 test]# grep test -R /tmp/test/mytest

/tmp/test/mytest/test:test:x:1003:1003::/home/test:/bin/bash

/tmp/test/mytest/test:@zhangying:*:1004:1004::/home/test:/bin/bash

递归显示匹配的内容,在test目录下面建个mytest目录,copy test目录下面的test文件到mytest下面,能看到上面的结果

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -A 3 root

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa

daemon:x:2:2:daemon:/sbin:/bin/false

mail:x:8:12:mail:/var/spool/mail:/bin/false

显示匹配root后面的3行

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -B 2 ftp

daemon:x:2:2:daemon:/sbin:/bin/false

mail:x:8:12:mail:/var/spool/mail:/bin/false

ftp:x:14:11:ftp:/home/ftp:/bin/false

显示匹配ftp前面的2行

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -C 2 ftp

daemon:x:2:2:daemon:/sbin:/bin/false

mail:x:8:12:mail:/var/spool/mail:/bin/false

ftp:x:14:11:ftp:/home/ftp:/bin/false

&nobody:$:99:99:nobody:/:/bin/false

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

显示匹配ftp前面的2行,后面的2行,以及本身

查看复制打印?

[root@krlcgcms01 test]# cat test |grep -2 ftp

daemon:x:2:2:daemon:/sbin:/bin/false

mail:x:8:12:mail:/var/spool/mail:/bin/false

ftp:x:14:11:ftp:/home/ftp:/bin/false

&nobody:$:99:99:nobody:/:/bin/false

zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash

显示匹配ftp前面的2行,后面的2行,以及本身,和-C用法一样

AWK:Linux 管理员的智能工具包

作者 Emmett Dulaney

AWK 实用工具带有其自己的自包含语言,它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。 AWK 是什么?

最简单地说,AWK 是一种用于处理文本的编程语言工具。AWK 实用工具的语言在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。在最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

尽管操作可能会很复杂,但命令的语法始终是:

awk '{pattern + action}' {filenames}

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。

了解字段

实用工具将每个输入行分为记录和字段。记录是单行的输入,而每条记录包含若干字段。默认的字段分隔符是空格或制表符,而记录的分隔符是换行。虽然在默认情况下将制表符和空格都看作字段分隔符(多个空格仍然作为一个分隔符),但是可以将分隔符从空格改为任何其它字符。

为了进行演示,请查看以下保存为 emp_names 的员工列表文件:

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

46019 BOGUE ROBERT PHOENIX AZ

46021 JUNE MICAH PHOENIX AZ

46022 KANE SHERYL UNKNOWN AR

46024 WOOD WILLIAM MUNCIE IN

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

46029 TUTTLE BOB MUNCIE IN

当 AWK 读取输入内容时,整条记录被分配给变量 $0。每个字段以字段分隔符分开,被分配给变量 $1、$2、$3 等等。一行在本质上可以包含无数个字段,通过字段号来访问每个字段。因此,命令

awk '{print $1,$2,$3,$4,$5}' names

将会产生的打印输出是

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

46019 BOGUE ROBERT PHOENIX AZ

46021 JUNE MICAH PHOENIX AZ

46022 KANE SHERYL UNKNOWN AR

46024 WOOD WILLIAM MUNCIE IN

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

46029 TUTTLE BOB MUNCIE IN

值得注意的一项重要内容是,AWK 解释由空格分隔的五个字段,但当它打印显示内容时,在每个字段间只有一个空格。利用为每个字段指定了唯一号码的功能,您可以选择只打印特定的字段。例如,只打印每条记录的姓名时,只需选择第二个和第三个字段进行打印:

$ awk '{print $2,$3}' emp_names

DULANEY EVAN

DURHAM JEFF

STEEN BILL

FELDMAN EVAN

SWIM STEVE

BOGUE ROBERT

JUNE MICAH

KANE SHERYL

WOOD WILLIAM

FERGUS SARAH

BUCK SARAH

TUTTLE BOB

$

您还可以指定按任何顺序打印字段,而无论它们在记录中是如何存在的。因此,只需要显示姓名字段,并且使其顺序颠倒,先显示名字再显示姓氏:

$ awk '{print $3,$2}' emp_names

EVAN DULANEY

JEFF DURHAM

BILL STEEN

EVAN FELDMAN

STEVE SWIM

ROBERT BOGUE

MICAH JUNE

SHERYL KANE

WILLIAM WOOD

SARAH FERGUS

SARAH BUCK

BOB TUTTLE

$

使用模式

通过包含一个必须匹配的模式,您可以选择只对特定的记录而不是所有的记录进行操作。模式匹配的最简单形式是搜索,其中要匹配的项目被包含在斜线 (/pattern/) 中。例如,只对那些居住在阿拉巴马州的员工执行前面的操作:

$ awk '/AL/ {print $3,$2}' emp_names

EVAN DULANEY

JEFF DURHAM

BILL STEEN

EVAN FELDMAN

STEVE SWIM

$

如果您不指定要打印的字段,则会打印整个匹配的条目:

$ awk '/AL/' emp_names

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

$

对同一数据集的多个命令可以用分号 (;) 分隔开。例如,在一行中打印姓名,而在另一行中打印城市和州名:

$ awk '/AL/ {print $3,$2 ; print $4,$5}' emp_names

EVAN DULANEY

MOBILE AL

JEFF DURHAM

MOBILE AL

BILL STEEN

MOBILE AL

EVAN FELDMAN

MOBILE AL

STEVE SWIM

UNKNOWN AL

$

如果没有使用分号 (print $3,$2,$4,$5),则会在同一行中显示所有内容。另一方面,如果分别给出两个打印语句,则会产生完全不同的结果:

$ awk '/AL/ {print $3,$2} {print $4,$5}' emp_names

EVAN DULANEY

MOBILE AL

JEFF DURHAM

MOBILE AL

BILL STEEN

MOBILE AL

EVAN FELDMAN

MOBILE AL

STEVE SWIM

UNKNOWN AL

PHOENIX AZ

PHOENIX AZ

UNKNOWN AR

MUNCIE IN

MUNCIE IN

MUNCIE IN

MUNCIE IN

$

只有在列表中找到 AL 时才会给出字段三和字段二。但是,字段四和字段五是无条件的,始终打印它们。只有第一组花括号中的命令对前面紧邻的命令 (/AL/) 起作用。

结果非常不便于阅读,可以使其稍微更清晰一些。首先,在城市与州之间插入一个空格和逗号。然后,在每两行显示之后放置一个空行:

$ awk '/AL/ {print $3,$2 ; print $4", "$5"\n"}' emp_names

EVAN DULANEY

MOBILE, AL

JEFF DURHAM

MOBILE, AL

BILL STEEN

MOBILE, AL

EVAN FELDMAN

MOBILE, AL

STEVE SWIM

UNKNOWN, AL

$

在第四和第五个字段之间,添加一个逗号和一个空格(在引号之间),在第五个字段后面,打印一个换行符 (\n)。在 AWK 打印语句中还可以使用那些可在 echo 命令中使用的所有特殊字符,包括:

\n(换行)

\t(制表)

\b(退格)

\f(进纸)

\r(回车)

因此,要读取全部五个最初由制表符分隔开的字段,并且也利用制表符打印它们,您可以编程如下

$ awk '{print $1"\t"$2"\t"$3"\t"$4"\t"$5}' emp_names

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

46019 BOGUE ROBERT PHOENIX AZ

46021 JUNE MICAH PHOENIX AZ

46022 KANE SHERYL UNKNOWN AR

46024 WOOD WILLIAM MUNCIE IN

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

46029 TUTTLE BOB MUNCIE IN

$

通过连续设置多项标准并用管道 (|) 符号将其分隔开,您可以一次搜索多个模式匹配:

$ awk '/AL|IN/' emp_names

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

46024 WOOD WILLIAM MUNCIE IN

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

46029 TUTTLE BOB MUNCIE IN

$

这样可找到每个阿拉巴马州和印第安那州居民的匹配记录。但是在试图找出居住在亚利桑那州的人时,出现了一个问题:

$ awk '/AR/' emp_names

46019 BOGUE ROBERT PHOENIX AZ

46021 JUNE MICAH PHOENIX AZ

46022 KANE SHERYL UNKNOWN AZ

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

$

员工 46026 和 46027 没有住在亚利桑那州;但是他们的名字中包含所搜索的字符序列。切记,当在 AWK 中进行模式匹配时,例如 grep、sed 或者大部分其他 Linux/Unix 命令,将在记录(行)中的任何位置查找匹配,除非指定进行其他操作。为解决这一问题,必须将搜索与特定字段联系起来。通过利用代字号 (?) 以及对特定字段的说明,可以达到这一目的,如下例所示:

$ awk '$5 ? /AR/' emp_names

46019 BOGUE ROBERT PHOENIX AZ

46021 JUNE MICAH PHOENIX AZ

46022 KANE SHERYL UNKNOWN AZ

$

代字号(表示匹配)的对应符号是一个前面带有感叹号的代字号 (!?)。这些字符通知程序,如果搜索序列没有出现在指定字段中,则找出与搜索序列相匹配的所有行:

$ awk '$5 !? /AR/' names

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

46017 FELDMAN EVAN MOBILE AL

46018 SWIM STEVE UNKNOWN AL

46024 WOOD WILLIAM MUNCIE IN

46026 FERGUS SARAH MUNCIE IN

46027 BUCK SARAH MUNCIE IN

46029 TUTTLE BOB MUNCIE IN

$

在这种情况下,将显示第五个字段中没有 AR 的所有行 — 包括两个 Sarah 条目,这两个条目确实包含 AR,但却是在第三个字段而不是第五个字段中。

花括号和字段分隔符

括号字符在 AWK 命令中起着很重要的作用。出现在括号之间的操作指出将要发生什么以及何时发生。当只使用一对括号时:

{print $3,$2}

括号间的所有操作同时发生。当使用多于一对的括号时:

{print $3}{print $2}

执行第一组命令,在该命令完成后执行第二组命令。注意以下两列清单的区别:

$ awk '{print $3,$2}' names

EVAN DULANEY

JEFF DURHAM

BILL STEEN

EVAN FELDMAN

STEVE SWIM

ROBERT BOGUE

MICAH JUNE

SHERYL KANE

WILLIAM WOOD

SARAH FERGUS

SARAH BUCK

BOB TUTTLE

$

$ awk '{print $3}{print $2}' names

EVAN

DULANEY

JEFF

DURHAM

BILL

STEEN

EVAN

FELDMAN

STEVE

SWIM

ROBERT

BOGUE

MICAH

JUNE

SHERYL

KANE

WILLIAM

WOOD

SARAH

FERGUS

SARAH

BUCK

BOB

TUTTLE

$

要利用多组括号进行重复查找,执行第一组中的命令直到完成为止;然后处理第二组命令。如果有第三组命令,则在第二组命令完成后执行它,以此类推。在所生成的打印输出中,有两个分隔的打印命令,因此先执行第一个命令,随后执行第二个命令,这样导致每个条目显示在两行而不是一行中。

区分两个字段的字段分隔符不一定始终是空格;它可以是任何可识别的字符。为进行演示,假定 emp_names 文件利用冒号而不是制表符来分隔字段:

$ cat emp_names

46012:DULANEY:EVAN:MOBILE:AL

46013:DURHAM:JEFF:MOBILE:AL

46015:STEEN:BILL:MOBILE:AL

46017:FELDMAN:EVAN:MOBILE:AL

46018:SWIM:STEVE:UNKNOWN:AL

46019:BOGUE:ROBERT:PHOENIX:AZ

46021:JUNE:MICAH:PHOENIX:AZ

46022:KANE:SHERYL:UNKNOWN:AR

46024:WOOD:WILLIAM:MUNCIE:IN

46026:FERGUS:SARAH:MUNCIE:IN

46027:BUCK:SARAH:MUNCIE:IN

46029:TUTTLE:BOB:MUNCIE:IN

$

如果试图通过指定所需要的第二个字段来打印姓氏

$ awk '{print $2}' emp_names

您最后会得到十二个空行。因为文件中没有空格,除了第一个字段之外没有可认别的字段。为解决这一问题,必须通知 AWK 是空格之外的另一个字符作为分隔符,有两种方法可通知 AWK 使用新的字段分隔符:使用命令行参数 -F,或在程序中指定变量 FS。两种方法的效果相同,只有一种例外情况,如下例所示:

$ awk '{FS=":"}{print $2}' emp_names

DURHAM

STEEN

FELDMAN

SWIM

BOGUE

JUNE

KANE

WOOD

FERGUS

BUCK

TUTTLE

$

$ awk -F: '{print $2}' emp_names

DULANEY

DURHAM

STEEN

FELDMAN

SWIM

BOGUE

JUNE

KANE

WOOD

FERGUS

BUCK

TUTTLE

$

在第一个命令中,头一条记录返回不正确的空行,而其他结果正确。直到读取第二条记录时,才识别字段

分隔符并正确地执行。通过使用 BEGIN 语句可以纠正这一缺点(在后文详述)。-F 的功能非常类似于 BEGIN,能够正确地读取第一条记录并按要求执行。

在本文开始处我曾提到,默认的显示/输出字段分隔符是空格。通过使用输出字段分隔符 (OFS) 变量,可以在程序中更改此特性。例如,要读取文件(由冒号分隔)并以短划线显示,则命令是

$ awk -F":" '{OFS="-"}{print $1,$2,$3,$4,$5}' emp_names

46012-DULANEY-EVAN-MOBILE-AL

46013-DURHAM-JEFF-MOBILE-AL

46015-STEEN-BILL-MOBILE-AL

46017-FELDMAN-EVAN-MOBILE-AL

46018-SWIM-STEVE-UNKNOWN-AL

46019-BOGUE-ROBERT-PHOENIX-AZ

46021-JUNE-MICAH-PHOENIX-AZ

46022-KANE-SHERYL-UNKNOWN-AR

46024-WOOD-WILLIAM-MUNCIE-IN

46026-FERGUS-SARAH-MUNCIE-IN

46027-BUCK-SARAH-MUNCIE-IN

46029-TUTTLE-BOB-MUNCIE-IN

$

FS 和 OFS 是(输入)字段分隔符和输出字段分隔符,它们只是一对可以在 AWK 实用工具中使用的变量。例如,要在打印时为每行编号,可以采用以下方式使用 NR 变量:

$ awk -F":" '{print NR,$1,$2,$3}' emp_names

1 46012 DULANEY EVAN

2 46013 DURHAM JEFF

3 46015 STEEN BILL

4 46017 FELDMAN EVAN

5 46018 SWIM STEVE

6 46019 BOGUE ROBERT

7 46021 JUNE MICAH

8 46022 KANE SHERYL

9 46024 WOOD WILLIAM

10 46026 FERGUS SARAH

11 46027 BUCK SARAH

12 46029 TUTTLE BOB

$

找出员工号码处于 46012 和 46015 之间的所有行:

$ awk -F":" '/4601[2-5]/' emp_names

46012 DULANEY EVAN MOBILE AL

46013 DURHAM JEFF MOBILE AL

46015 STEEN BILL MOBILE AL

$

添加文本

可以按照添加控制序列或其他字符的相同方式将文本添加到显示中。例如,要将分隔符从空格改为冒号,则命令是

awk '{print $1":"$2":"$3":"$4":"$5}' emp_names > new_emp_names

在这种情况下,字符 (:) 包含在引号 ("/") 中,它被添加到每个字段之间。在引号之间的值可以是任何内容。例如,创建一个关于居住在阿拉巴马州的员工的外观类似数据库的显示:

$ awk '$5 ~ /AL/ {print "NAME: "$2", "$3"\nCITY-STATE:

"$4", "$5"\n"}' emp_names

NAME: DULANEY, EVAN

CITY-STATE: MOBILE, AL

NAME: DURHAM, JEFF

CITY-STATE: MOBILE, AL

NAME: STEEN, BILL

CITY-STATE: MOBILE, AL

NAME: FELDMAN, EVAN

CITY-STATE: MOBILE, AL

NAME: SWIM, STEVE

CITY-STATE: UNKNOWN, AL

$

数学操作

AWK 除了提供文本功能,还提供全部范围的算术操作符,包括以下符号:

+ 将数字相加

- 减

* 乘

/ 除

^ 执行指数运算

% 提供模

++ 将变量值加一

+= 将其他操作的结果分配给变量

— 将变量减一

-= 将减法操作的结果分配给变量

*= 分配乘法操作的结果

/= 分配除法操作的结果

%= 分配求模操作的结果

例如,假定您的机器上存在以下的文件,详细地列出硬件商店中的物品:

$ cat inventory

hammers 5 7.99

drills 2 29.99

punches 7 3.59

drifts 2 4.09

bits 55 1.19

saws 123 14.99

nails 800 .19

screws 80 .29

brads 100 .24

$

第一项业务定单是通过将第二个字段(数量)的值乘以第三个字段(价格)的值,计算每种物品的库存价值:

$ awk '{print $1,"QTY: "$2,"PRICE: "$3,"TOTAL: "$2*$3}' inventory

hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95

drills QTY: 2 PRICE: 29.99 TOTAL: 59.98

punches QTY: 7 PRICE: 3.59 TOTAL: 25.13

drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18

bits QTY: 55 PRICE: 1.19 TOTAL: 65.45

saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77

nails QTY: 800 PRICE: .19 TOTAL: 152

screws QTY: 80 PRICE: .29 TOTAL: 23.2

brads QTY: 100 PRICE: .24 TOTAL: 24

$

如果这些行本身并不重要,您只是希望确定商店中有多少件物品,则可以分配一个普通变量,按照每条记录中的物品数量增加:

$ awk '{x=x+$2} {print x}' inventory

5

7

14

16

71

194

994

1074

1174

$

根据这一数据,商店中有 1174 件物品。第一次执行时,变量 x 没有值,因此它采用第一行第二个字段的值。第二次执行时,它保留了第一行的值并加上第二行的值,以此类推,直到达到累计的总合。 可以应用相同的过程来确定现有库存的总价值:

$ awk '{x=x+($2*$3)} {print x}' inventory

39.95

99.93

125.06

133.24

198.69

2042.46

2194.46

2217.66

2241.66

$

因此,1174 件物品的价值是 $2,241.66。虽然这一过程可以获得总计值,但它的外观很差,需要加工成实际的报表。利用一些附加项,很容易使显示变得更整洁:

$ awk '{x=x+($2*$3)}{print $1,"QTY: "$2,"PRICE: "$3,"TOTAL: "$2*$3,"BAL: "x}' inventory

hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95 BAL: 39.95

drills QTY: 2 PRICE: 29.99 TOTAL: 59.98 BAL: 99.93

punches QTY: 7 PRICE: 3.59 TOTAL: 25.13 BAL: 125.06

drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18 BAL: 133.24

bits QTY: 55 PRICE: 1.19 TOTAL: 65.45 BAL: 198.69

saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77 BAL: 2042.46

nails QTY: 800 PRICE: .19 TOTAL: 152 BAL: 2194.46

screws QTY: 80 PRICE: .29 TOTAL: 23.2 BAL: 2217.66

brads QTY: 100 PRICE: .24 TOTAL: 24 BAL: 2241.66

$

该过程提供了每条记录的清单,同时将总价值分配给库存值,并保持商店资产的运作平衡。

BEGIN 和 END

使用 BEGIN 和 END 语句可以分别指定在处理实际开始之前或者完成之后进行操作。BEGIN 语句最常用于建立变量或显示标题。另一方面,END 语句可用于在程序结束后继续进行处理。

在前面的示例中,利用以下例程生成了物品的总价值:

awk '{x=x+($2*$3)} {print x}' inventory

该例程在运行总计累加时显示了文件中的每一行。没有其他方法可以指定它,而不让在每一行进行打印也导致它始终不打印出来。但是,利用 END 语句可以避免这一问题:

$ awk '{x=x+($2*$3)} END {print "Total Value of Inventory:"x}' inventory

Total Value of Inventory: 2241.66

$

定义了变量 x,它对每一行进行处理;但是,在所有处理完成之前不会生成显示。尽管可以作为独立例程使用,它也可以置入到先前的代码列表,添加更多信息并生成更完整的报表:

$ awk '{x=x+($2*$3)} {print $1,"QTY: "$2,"PRICE:

"$3,"TOTAL: "$2*$3} END {print "Total Value of Inventory: " x}' inventory

hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95

drills QTY: 2 PRICE: 29.99 TOTAL: 59.98

punches QTY: 7 PRICE: 3.59 TOTAL: 25.13

drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18

bits QTY: 55 PRICE: 1.19 TOTAL: 65.45

saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77

nails QTY: 800 PRICE: .19 TOTAL: 152

screws QTY: 80 PRICE: .29 TOTAL: 23.2

brads QTY: 100 PRICE: .24 TOTAL: 24

Total Value of Inventory: 2241.66

$

BEGIN 命令与 END 的工作方式相同,但它建立了那些需要在完成其他工作之前所做的项目。该过程最常见的目的是创建报表的标题。此例程的语法类似于

$ awk 'BEGIN {print "ITEM QUANTITY PRICE TOTAL"}'

输入、输出和源文件

AWK 工具可以从文件中读取其输入,正如在此之前所有示例所做的那样,它也可以从其他命令的输出中获取输入。例如:

$ sort emp_names | awk '{print $3,$2}'

awk 命令的输入是排序操作的输出。除了 sort,还可以使用任何其他的 Linux 命令 — 例如 grep。该过程允许您在离开所选定字段前对文件执行其他操作。

类似于解释程序,AWK 使用输出改向操作符>和>>将其输出放入文件中而不是标准输出设备。这些符号的作用类似于它们在解释程序中的对应符号,因此>在不存在文件时创建文件,而>>追加到现有文件的尾部。请看以下的示例:

$ awk '{print NR, $1 ) > "/tmp/filez" }' emp_names

$ cat /tmp/filez

1 46012

2 46013

3 46015

4 46017

5 46018

6 46019

7 46021

8 46022

9 46024

10 46026

11 46027

12 46029

$

检查该语句的语法,您会看到输出改向是在打印语句完成后进行的。必须将文件名包含在引号中,否则它只是一个未初始化的 AWK 变量,而将指令联接起来会在 AWK 中产生错误。(如果不正确地使用改向符号,则 AWK 无法了解该符号意味着“改向”还是一个关系操作符。)

在 AWK 中输出到管道也类似于解释程序中所实现的相同操作。要将打印命令的输出发送到管道中,可以在打印命令后附加管道符号以及命令的名称,如下所示:

$ awk '{ print $2 | "sort" }' emp_names

BOGUE

BUCK

DULANEY

DURHAM

FELDMAN

FERGUS

JUNE

KANE

STEEN

SWIM

TUTTLE

WOOD

$

这是输出改向的情况,必须将命令包含在引号中,而管道的名称是被执行命令的名称。

AWK 所使用的命令可以来自两个地方。首先,可以在命令行中指定它们,如示例中所示。其次,它们可以由源文件提供。如果是这种情况,通过 -f 选项将这种情况向 AWK 发出警告。演示如下:

$ cat awklist

{print $3,$2}

{print $4,$5,"\n"}

$

$ awk -f awklist emp_names

EVAN DULANEY

MOBILE AL

JEFF DURHAM

MOBILE AL

BILL STEEN

MOBILE AL

EVAN FELDMAN

MOBILE AL

STEVE SWIM

UNKNOWN AL

ROBERT BOGUE

PHOENIX AZ

MICAH JUNE

PHOENIX AZ

SHERYL KANE

UNKNOWN AR

WILLIAM WOOD

MUNCIE IN

SARAH FERGUS

MUNCIE IN

SARAH BUCK

MUNCIE IN

BOB TUTTLE

MUNCIE IN

$

注意,在源文件中的任何地方或者在命令行中调用它时,不使用单引号。单引号只用于区别命令行中的命令与文件名称。

如果简单的输出不能处理您的程序中所需要的复杂信息,则可以尝试由 printf 命令获得的更加复杂的输出,其语法是

printf( format, value, value ...)

该语法类似于 C 语言中的 printf 命令,而格式的规格是相同的。通过插入一项定义如何打印数值的规格,可以定义该格式。格式规格包含一个跟有字母的 %。类似于打印命令,printf 不必包含在圆括号中,但是可以认为使用圆括号是一种良好的习惯。

下表列出 printf 命令提供的各种规格。

规格说明

%c 打印单个 ASCII 字符

%d 打印十进制数

%e 打印数字的科学计数表示

%f 打印浮点表示

%g 打印 %e 或 %f;两种方式都更简短

%o 打印无符号的八进制数

s 打印 ASCII 字符串

%x 打印无符号的十六进制数

%% 打印百分号;不执行转换

可以在 % 与字符之间提供某些附加的格式化参数。这些参数进一步改进数值的打印方式:

参数说明

- 将字段中的表达式向左对齐

,width 根据需要将字段补齐到指定宽度(前导零使用零将字段补齐)

.prec 小数点右面数字的最大字符串宽度或最大数量

printf 命令能够控制并将数值从一种格式转换为另一种格式。当需要打印变量的值时,只需提供一种规格,指示 printf 如何打印信息(通常包含在双引号中)即可。必须为每个传递到 printf 的变量包含一个规格参数;如果包含过少的参数,则 printf 不会打印所有的数值。

处理错误

AWK 工具报告所发生错误的方式很令人恼火。一个错误会阻碍任何操作的进行,所提供的错误信息非常含混不清:

awk: syntax error near line 2

awk: bailing out near line 2

您可能会花几小时的时间查看第 2 行,试图找出它为什么阻碍程序运行;这就是支持使用源文件的一个有力论据。接下来的步骤

阅读 Linux 平台上 Oracle 的常见问题解答

访问并收藏 Linux 技术中心

阅读 Dale Dougherty 和 Arnold Robbins 的著作 sed & awk, 2nd Edition(O'Reilly & Associates 出版社)。

切记有两条规则可以帮助您避免出现语法错误:

1. 确保命令位于括号中,而括号位于单引号中。没有使用这些字符之一必然导致程序无法运行。

2. 搜索命令需要位于斜线之间。要找出住在印第安那州的员工,您必须使用“/IN/”而不是“IN”。 结论

尽管 AWK 完全代表另外的含意,但它应该是管理员智能工具包的首字母缩写。连同 SED 一起,AWK 实用工具是 Linux 管理员所拥有的功能最强大和灵活的工具之一。通过了解其语言的一些特性,您可以开辟出能够简化任务的领域,否则这些任务将会是非常费时和困难的。

更多相关推荐:
gmat写作北美范文分析

gmat写作北美范文分析学习GMAT写作往往离不开北美范文但其中良莠不齐并非篇篇能称之为范毕竟它们不是ACTETS所钦定的文章如此说来OfficialGuide上的范文就弥足珍贵无论6分的还是5分4分的都要仔细...

gmat 真题资料

真题资料1新东方教材包括阅读逻辑语法数学国内GMAT考试笔考真题孙远绿皮作文宝典2TheOfficialGuideforGMATReviewGMAC出版的GMAT备考资料请高度重视题目的解释看看书上的说法1Mo...

应该怎样快速提高gmat写作速度 太傻咨询网

应该怎样快速提高gmat写作速度太傻咨询网打字速度影响考生的gmat写作速度太傻gmat频道为大家带来gmat写作速度怎么才能快速提高希望对大家gmat备考有所帮助gmat写作考试的备考复习中还有一项影响写作速...

GMAT argument写作七宗罪的记忆方法

AA七宗罪的记忆方法因果证分析了两个晚上的AA发现quot七宗罪quot确实是好东西就是那些quot罪quot太多而且过于零散很难记忆因此将七宗罪分类整理了一下按照论证的原因结果论证过程三部分归为三个类别因果证...

gmat 作文模板

Inthisreporttheauthorconcludesthat结论Tosupporthisconclusiontheauthorpointsoutthat论据1Inadditiontheauthorrea...

GMAT写作Argument范文下载三

摘要GMAT写作在复习的过程中多看一些经典的范文对于写作的提高非常有帮助所以GMAT资料下载的小编为考生整理了GMAT写作Argument范文让大家更好的备考写作在GMAT写作考试中获得好成绩GMAT写作Arg...

gmat语法全总结

GMAT个人语法笔记说明本笔记全面覆盖PREP20xx所有知识点Manhattan所有语法点新东方丽丽所讲的我个人觉得靠谱的语法点管卫东语法点以及平时真题时遇到的语法点有很强的覆盖性编撰此笔记旨在方便各位CDe...

gmat语法总结大全

Like和As的混合考题特点选项中同时存在As结构和Like结构注意只有like或者只有as的不属于此类两种结构都有可能成为正确答案一般情况下As结构和Like结构同时在选项中出现的时候只有一个结构是符合下面的...

gmat学习计划及复习方法分享

gmat学习计划及复习方法分享太傻留学gmat考试频道小编为考生们总结20xxgmat学习计划及复习方法希望考生们都能有一套适合自己的20xxgmat学习计划顺利备考20xxgmat学习计划及复习方法如下阶段一...

gmat 复习攻略 GMAT备考计划

gmat复习攻略GMAT备考计划gmat官方调查数据显示如果考生想达到600700分需要的备考时间至少为100小时50的考生现在会选择49周备考时间每周27小时学习时间552的学生在第一次考试之后觉得准备不充分...

GRE argument官方满分范文分析

argument全部官方范文分析写在前面的话1官方范文的重要性不言而喻论坛里对官方范文的态度也有褒有贬有人说这些6分的官方文章都是大牛写出来的我们学不来于是有的同学的重心就转向了北美范文但有一点是不可否认的官方...

GRE写作argument范文

GRE写作Argument高分范文题目ThefollowingappearedinamemorandumfromthegeneralmanagerofKNOWradiostationquotKNOWshould...

gmat awa (2篇)