awk编程基础(2)

来源:互联网 发布:mac airdrop怎么用 编辑:程序博客网 时间:2024/05/31 19:04
4) 读入awk以外的Shell变量有时需要将awk以外的变量读入到awk之中,通常有两种方法:a. 直接引用外部变量aa="字符串"awk ' { print "'$aa'" }' 次种方法,如果变量aa的值是一个汉字字符串,则在SCO Unix3.0上运行将显示不出来,在5.0上没有问题。b. 间接引用外部变量aa="string"awk '{ print bb }' bb=$aa执行后每一次回车都将显示一个字符串string,该字符串是由awk中的print语句显示的,其中变量bb的值通过后面的bb=$aa引入。对于汉字字符串的赋值在SCO Unix3.0上运行时还需注意,多个赋值语句,使用汉字字符串的语句应放在后面(在5.0上没有这种情况):aa=“计算机使用指南”bb=“computer guide”awk '{ print cc dd }' cc=$bb dd=$aa filename数据的处理是以“记录”(recoder)为单位的,也就是awk 在做处理时,是一个记录一个记录地处理。每个记录的缺省值是一行(line),一个记录又被分为多个字段(fields)。 如何将输入分解成记录(records)awk 语言会把输入分解成记录(record)。记录与记录之间是以记录分隔符(record separator)隔开的,其缺省值是文件中的换行符(newline character),因此在缺省状态下输入数据的每一行是一个记录。记录分隔符随着内部变量 RS 的改变而改变。RS 是一个字串,如“|”。它的缺省值是"/n"。仅有 RS 的第一个字符是有效的,而其它字符会被忽略。内部变量 FNR 会储存目前的输入文件已经被读取的记录的个数。内部变量 NR 会储存目前为止所有的输入文件已经被读取记录的个数。 字段(field)awk 会自动将每个记录按缺省值分解成多个字段 (field)。awk 的缺省动作会认为字段之间是以 whitespace 为分隔的。这里,whitespace 的意思是一个或多个空格或 tabs。 在 awk 程序里面,以'$1'表示第一个字段,'$2'表示第二个字段,依此类推。举个例子,假设输入的一行如下所示: This seems like a pretty nice example. 第一个字段或 $1 是'This',第二个字段或 $2 是 'seems',依此类推。有个地方需要特别注意,第七个字段或 $7 是'example.'而非'example'。不论有多少字段,$NF 可用来表示一个记录的最后一个字段。以上面的例子为例,$NF 与 $7 相同,也就是'example.'。 NF 是一个内部变量,它的值表示目前这个记录之字段的个数。 $0,看起来好像是第零个字段,它是一个特例,它表示整个记录。 下面是一个较复杂的例子: awk '$1~/foo/ { print $0 }' Earth这个例子是把输入文件'Earth'的每个记录的第一个字段作检查,如果它含有子字串'foo',则这一个记录会被输出。 如何将记录分解成字段awk 根据 field separator(字段分隔符)将一个记录分解成若干字段。field separator 以内部变量 FS 表示。 举个例子,假如 field separator 是'oo',则下面的行: moo goo gai pan 会被分成三个字段:'m'、' g'、' gai pan'。 在 awk 程序里,可以使用'='来改变 FS 的值。 例如: awk 'BEGIN { FS="," }; { print $2 }' 输入行如下: John Q. Smith, 29 Oak St., Walamazoo, MI 42139 执行awk的结果将输出字符串 ' 29 Oak St.'(将第二个字段打印出)。BEGIN 后面的 action 会在第一个记录被读取之前执行一次。 4.1.2 输出 在awk程序里,actions 最常做的事就是输出(printing)。简单的输出,使用 print描述。复杂格式的输出,使用 printf 描述。print 语句print语句用在简单、标准的输出格式。格式:print var1,[ var2,……],str1,[str2,……,strn ]说明:在print 语句后面,可以跟变量或字符串,变量或字符串可以有多个,语句执行后,跟在print 语句后面的变量值或字符串将被显示到屏幕上。多个变量或字符串之间可以是逗号“,”或空格,使用逗号时,显示出的各个字符串之间会有空格分隔;使用空格时,显示出的各个字符串将连接起来,形成一个长的字符串。 如:echo “fir sec thir four five”|awk ‘{ print $1,$2,$3,$4 }’其执行结果为fir sec thir four 而:echo “fir sec thir four five”|awk ‘{ print $1 $2 $3 $4 }’的结果为firsecthirfourprint语句输出后自动换行,如有第二个显示语句,将从下一行输出。如果 'print'描述之后没有跟着任何东西,它与'print $0'的效果一样,它会输出现在的记录(record)。要输出空白行可使用'print ""'。 输出一段固定的文字,可用双引号将文字的两边括起来,例如'print "Hello there"'。 下面的例子,会把每个输入记录的前二个字段输出: awk '{ print $1,$2 }' shipped 2) 输出分隔符 前面我们已提过print语句后面多个输出字段(变量)之间可以用逗点使输出分隔开来,事实上,你可以任何设定你所需要的输出分隔符,OFS 就是用来设定输出分隔符的内部变量。其缺省值为空格。 下面这个例子会输出每个记录的第一个字段和第二个字段,此二个字段之间在输出时是以分号';'分开的,每行输出之后会加入一个空白行。 awk 'BEGIN { OFS=";" ORS="/n/n" } {print $1, $2}' earth 3) printf语句 printf 语句会使得输出格式较容易精确地控制。printf 语句可以指定每个 item 输出的宽度,也可以指定数字的各种格式。printf 语句的格式如下:printf format, item1, item2, ...如:printf "%4s%10s%10s/n","str1","str2","str3"或:printf ("%4s%10s%10s/n","str1","str2","str3") print 与 printf 的差别是在于 format, printf 的参数比 print多了字符串 format。format 的格式与 C语言 中的 printf语句格式相同。 printf 并不会做自动换行的动作。内部变量 OFS 与 ORS 对 printf 语句没有任何影响。 格式的指定以字符'%'开始,后面接着格式控制字母。 格式控制字母如下所示:'c' 将数字以 ASCII 字符输出。 例如 'printf "%C",65'会输出字符'A'。'd' 输出十进位的整数。'e' 将数字以科学记数的形式输出。 例如 printf "%4.3e",1950 结果会输出'1.950e+03'。'f' 将数字以浮点的形式输出。'g' 将数字以科学记数的形式或浮点的形式输出。数字的绝对值如果大于 等于0.0001则以浮点的形式输出,否则以科学符号的形式输出。'o' 输出无符号的八进位整数。's' 输出一个字串。'x' 输出无符号的十六进位整数。10至15以'a'至'f'表示。'X' 输出无符号的十六进位整数。10至15以'A'至'F"表示。'%' 它并不是真正的格式控制字母,”%%"将输出‘%'。 在 % 与格式控制字母之间可加入 modifier,是用来进一步控制输出的格式。可能的 modifier 如下所示:'width' 这一个数字指示相对应的字段输出时的宽度。例如:'-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在被指定的宽度向右靠齐。例如:printf "%-6s", "foo" 会输出'foo '。 printf "%6s","foo" 会输出' foo'。 width 的值是一个最小宽度而非最大宽度。如果一个 item 的值需要的宽度比 width 大,则不受 width 的影响。例如 printf "%4s","foobar" 将输出'foobar'。'.prec' 此数字指定输出时的精确度。它指定小数点右边的位数。如果是要输出一个字串,它指定此字串最多会被输出多少个字符。4.2 控制语句 在 awk 程序里面,控制语句诸如 if、while 等的使用与 C语言类似。 很多的控制语句会包括其它的语句,被包括的语句称为程序体(body)。假如body 里面包括一个以上的语句,必须以大括弧 { } 将这些语句括起来(这与Shell的语法有所区别),而各个语句之间需以换行(newline)或分号隔开。 1) if 语句语法: if ( 条件 ) { body1 } [ else { body2 } ]其中,if,else 是关键字,如果使用必须保留,程序体中可以有多条语句。如果条件(condition)为真(true),则执行程序体1中的语句,否则执行程序体2。 例1: if ( x == 0) #变量x是否为0 print "x equal zero" #为0则打印"x equal zero" else #否则 print "x not equal zero" #则打印"x not equal zero" 当然也可以只要“if部分”而不使用“else部分”如例2: if ( x == 0 ) { print "x equal zero" x=x+1 } 说明:if中的程序体通常要用大括号括起来,但在有些情况下可以省略。如在例1中,不论在if后面还是else后面,过程体中总共只有一句,在这中情况下就不需要使用大括号。而在例2中,if后面过程体中的语句多于一句,就必须使用大括号,否则意义会有所区别。 2)while 语句语法: while ( 条件 ) { body }while 语句执行后所做的第一件事就是测试‘条件’是否为真。为真则执行 body 中的语句,执行完后,再进行测试,如‘条件’仍为真,则 body 会被再度执行。这个过程会一直被重复直到‘条件’不再为真。如果‘条件’的第一次测试就是假(false),则body 会被跳过去,程序将执行后面的语句。通常body中的语句都会改变条件中所使用变量的值,或当达到某个条件后跳出循环,否则,while语句将会无限执行下去,出现所谓的死循环。 下面的例子会输出每个输入记录(record)的前三个字段。 awk '{ i=1 while (i <= 3) { printf(“%s”,$i) i++ } print “” #换行 }'3)do-while 语句 语法:do body while ( 条件 ) do-while 语句执行时,不管条件成立与否,都首先执行程序体(body)一次,然后再判断是否为真,为真则会重复执行 body,否则退出do-while循环语句。 下面的例子会将每个输入记录输出十次。 awk '{ i= 1 do { print $0 i++ } while (i <= 10) }' 文件名 4)for 语句 语法: for (赋初值;条件;动作) { body }此语句开始时会执行初始赋值(initialization),然后比较条件是否为真,只要条件(condition)为真,就执行‘动作’和body ,然后重新判断条件,重新执行,直到条件为假为止。