既然 awk 处理输入文件,他使用几个变量。一些是可以编辑的,一些是只读的。
域分隔符,既不是一个单独的字符也不是一个普通的表达式,是控制 awk 把一个输入分割成几个域。输入记录按分割定义进行字符顺序扫描;域就是在相符的那些文字中间的那部分。
域分隔符代表内建的变量 FS
,注意POSIX标准的shell使用的变量 IFS
和他是有一些区别的。
域分隔符变量的值可以在 awk 程序中用赋值操作符 = 来改变。通常最好的执行时间是一开始也就是还没有处理任何输入的时候,因此第一个记录就被随合适的分隔符一起读取。要这么做,清使用特殊的 BEGIN pattern。
以下的例子,我们编制了一条命令来显示系统里的所有用户及其描述:
kelly is in ~>
awk'BEGIN { FS=":" } { print $1 "\t" $5 }'
/etc/passwd
--output omitted-- kelly Kelly Smith franky Franky B. eddy Eddy White willy William Black cathy Catherine the Great sandy Sandy Li Wongkelly is in ~>
在一个 awk 脚本中,它看起来像这样:
kelly is in ~>
catprintnames.awk
BEGIN { FS=":" } { print $1 "\t" $5 }kelly is in ~>
awk-f
printnames.awk /etc/passwd
--output omitted--
小心地选择输入分隔域来防止出现问题。一个例子来说明这个:说你需要输入想这样的行的形式:
“Sandy L. Wong, 64 Zoo St., Antwerp, 2000X”
你这样写了一个打印出记录中人的名字的命令行或者是脚本:
awk 'BEGIN { FS="," } { print $1, $2, $3 }'
inputfile
但是可能一个人有PhD,而且可能写成这样:
“Sandy L. Wong, PhD, 64 Zoo St., Antwerp, 2000X”
你的 awk 会给出错误的输出。需要的话,使用额外的一个 awk 或者 sed 来统一数据输出的格式。
默认的输入分隔符是一个或多个空格和制表符。
在输出中域通常被空格分隔。当你对 print 命令使用正确的语法且字段用逗号分隔时,这将很明显的:
kelly@octarine ~/test>
cattest
record1 data1 record2 data2kelly@octarine ~/test>
awk'{ print $1 $2}'
test
record1data1 record2data2kelly@octarine ~/test>
awk'{ print $1, $2}'
test
record1 data1 record2 data2kelly@octarine ~/test>
如果你不输入逗号, print 将把输出的项目全部当成一个字段,因此省略默认输出 分隔符, OFS
的使用。
在摄制了这个内建变量的值之后任何字符串可以被用作一个输出域。
整个 print 语句的输出叫做输出记录。每个在输出记录里的print命令的结果,输出一个叫做 输出记录分隔符 ORS
的字符串。这个变量的默认值是 “\n”,一个换行符。因此,每个 print 语句生成一个单独的行。
要改变输出域和记录的,只要给 OFS
和 ORS
赋新的值:
kelly@octarine ~/test>
awk'BEGIN { OFS=";" ; ORS="\n-->\n" } \ { print $1,$2}'
test
record1;data1 --> record2;data2 -->kelly@octarine ~/test>
如果 ORS
的值不包含换行,那么程序中的输出就会输出成一个单独行。
内建的 NR
包含了处理过的记录的数量。在读入一个新的输入行之后他会自行增加一次。你可以用它来计算记录的总数,或者在每个输出记录中:
kelly@octarine ~/test>
catprocessed.awk
BEGIN { OFS="-" ; ORS="\n--> done\n" } { print "Record number " NR ":\t" $1,$2 } END { print "Number of records processed: " NR }kelly@octarine ~/test>
awk-f
processed.awk test
Record number 1: record1-data1 --> done Record number 2: record2-data2 --> done Number of records processed: 2 --> donekelly@octarine ~/test>
除了内建的变量之外,你也可以定义自己的变量。当 awk 碰到一个不存在的变量(没有事先定义的)的引用时,这个变量就被创建并且使用一个空字符串进行赋值。对于后来所有的引用,就是该变量最后被赋予的那个值。变量可以是一个字符串或者一个数字。输入域的内容也可以被赋予变量。
值可以直接用 = 来赋值,或者你可以使用现有变量的值和其他操作符组合:
kelly@octarine ~>
catrevenues
20021009 20021013 consultancy BigComp 2500 20021015 20021020 training EduComp 2000 20021112 20021123 appdev SmartComp 10000 20021204 20021215 training EduComp 5000kelly@octarine ~>
cattotal.awk
{ total=total + $5 } { print "Send bill for " $5 " dollar to " $4 } END { print "---------------------------------\nTotal revenue: " total }kelly@octarine ~>
awk-f
total.awk test
Send bill for 2500 dollar to BigComp Send bill for 2000 dollar to EduComp Send bill for 10000 dollar to SmartComp Send bill for 5000 dollar to EduComp --------------------------------- Total revenue: 19500kelly@octarine ~>
类似于C的简写 VAR
+= value 也是可以接受的。
当我们使用 awk 脚本时, 第 5.3.2 节 “写输出文件” 的例子会变得更加容易:
kelly@octarine ~/html>
catmake-html-from-text.awk
BEGIN { print "<html>\n<head><title>Awk-generated HTML</title></head>\n<body bgcolor=\"#ffffff\">\n<pre>" } { print $0 } END { print "</pre>\n</body>\n</html>" }
而且当用 awk 来替代 sed 后,命令也变得更加直截了当:
kelly@octarine ~/html>
awk-f
make-html-from-text.awk testfile
>file.html
![]() |
在你系统上的awk例子。 |
---|---|
我们再次回到包含你系统启动脚本的目录。输入一个和以下相似的命令来查看更多 awk 命令的使用方法:
|