zoukankan      html  css  js  c++  java
  • Linux文本处理三剑客之awk学习笔记06:输出操作

    输出操作

    awk可以通过print或者printf将数据输出到标准输出或者重定向到文件中。

    print

    print我们已经使用过很多次了。其实它本质是一个输出函数,即有小括号。

    print (elem1,elem2,elem3...)
    print elem1,elem2,elem3...

    输出的每一个东西,我们可以称之为字段/元素,在书写时使用逗号分隔多个字段。一个print当中的所有字段组合起来就是一条记录。在输出的时候,print会使用预定义变量OFS来分隔多个字段,多个print语句的输出就是多条记录,它们之间使用预定义变量ORS来分隔。这也是为什么默认情况下,print输出的多个字段使用空格分隔,多个print语句的输出结果使用换行分隔的原因了。

    # awk 'BEGIN{OFS=":";ORS="!!!
    ";print "a","b","c";print "d","e","f"}'
    a:b:c!!!
    d:e:f!!!
    # awk 'BEGIN{OFS=":";ORS="!!!
    ";print("a","b","c");print("d","e","f")}'
    a:b:c!!!
    d:e:f!!!

    每个输出的字段都会被print转换成字符串格式后输出,即便是纯数字。若不是纯数字,则要将输出的字段使用双引号包裹,否则会被认为是变量而进行变量替换。

    # awk 'BEGIN{print abc}'
    
    # awk 'BEGIN{print "abc"}'
    abc

    如果输出的内容包含特殊符号(例如重定向字符),则需要使用小括号包裹。

    [root@c7-server ~]# ls -l 4
    ls: cannot access 4: No such file or directory
    [root@c7-server ~]# awk 'BEGIN{print 5>4}'
    [root@c7-server ~]# ls -l 4
    -rw-r--r-- 1 root root 2 Jan  9 20:28 4
    [root@c7-server ~]# cat 4
    5
    [root@c7-server ~]# awk 'BEGIN{print(5>4)}'
    1

    print除了在输出数字时会将其转换为字符串再输出以外,当输出小数的时候,会按照预定义变量OFMT(Output ForMaT)定义的格式进行格式化后输出。该变量的值定义的格式与printf()定义的格式相同。格式化输出的格式在讲解printf()时会再详述。OFMT的默认值为“%.6g”表示整数部分+小数部分最多6位。

    # awk 'BEGIN{print 3.12432623}'
    3.12433

    同理,可修改OFMT来修改print对于小数的输出行为。

    # awk 'BEGIN{OFMT="%.2f";print 3.99989}'
    4.00
    # awk 'BEGIN{OFMT="%d";print 3.99989}'
    3
    # awk 'BEGIN{OFMT="%.0f";print 3.99989}'
    4

    printf

    print的输出格式是由ORS和OFS所决定的,而printf是格式化输出,其输出格式由其自身所决定。

    printf format,item1,item2,...

    format:指定了要输出的格式,其中包含了多个“%+控制字母”的东西表示占位符,其会被format之后出现的各个item所依次(默认)替换。

    # awk 'BEGIN{printf "My name is %s,My age is %d
    ","alongdidi",29}'
    My name is alongdidi,My age is 29

    如果format当中没有任何占位符的话,那么直接打印format字面内容,format后续的所有item都可以无视。

    # awk 'BEGIN{printf "alongdidi
    ",29,"male","single"}'
    alongdidi

    常见的占位符(%+控制字母)。

    %c:根据编码表(ASCII)打印字符。

    # awk 'BEGIN{printf "%c
    ",65}'
    A

    %d, %i:打印十进制整数,如果遇到小数则直接丢弃小数部分保留整数部分。

    # awk 'BEGIN{printf "%d
    %d
    ",30,30.3}'
    30
    30

    %e, %E:使用科学计数法打印一个数字。

    # awk 'BEGIN{printf "%e
    ",10000000000}'
    1.000000e+10

    %f:打印浮点数(小数)。小数位足够长时会取近似值。

    # awk 'BEGIN{printf "%f
    ",3.1415926}'
    3.141593

    %g, %G:使用科学计数法或者浮点数来显示,具体使用哪种取决于这两种表示法谁占用的字符数较少。

    # awk 'BEGIN{printf "%g
    ",3.14}'
    3.14
    # awk 'BEGIN{printf "%g
    ",33333333333333333333333.14}'
    3.33333e+22

    %o:将十进制数转换成八进制数并以字符串格式打印出来。

    # awk 'BEGIN{printf "%o
    ",8}'
    10

    %x:将十进制数转换成十六进制数并以字符串格式打印出来。

    # awk 'BEGIN{printf "%x
    ",16}'
    10

    %s:打印字符串。

    %%:打印百分号。

    # awk 'BEGIN{printf "%d%%
    ",100}'
    100%

    还可以使用修饰符,修饰符位于%和控制字母之间。

    N$:N是一个整数。默认情况下各item按位(出现次序)与format中的占位符替换。而该修饰符可以改变这个顺序。

    # awk 'BEGIN{printf "%s %s %s
    ","I","love","u"}'
    I love u
    # awk 'BEGIN{printf "%3$s %2$s %1$s
    ","I","love","u"}'
    u love I

    可重复。

    # awk 'BEGIN{printf "%2$s %2$s %2$s
    ","I","love","u"}'
    love love love

    width:指定最短字符宽度。宽度不足时使用空格(这里使用下划线“_”表示)在字符串左边填充,超出宽度则该修饰符无效。

    # awk 'BEGIN{printf "%4s
    ","foo"}'
    _foo
    # awk 'BEGIN{printf "%4s
    ","foobar"}'
    foobar

    -:减号。默认情况下字符串右对齐(所以空格在左边填充),该修饰符使其左对齐。

    # awk 'BEGIN{printf "%5s
    %-5s
    ","ni","ni"}'
    ___ni
    ni___

    space:空格。针对于数值表示其正负性。如果是正数在其前添加一个空格,对于负数则不改变。

    # awk 'BEGIN{printf "% d
    % d
    ",1,-1}'
    _1
    -1

    +:加号。与空格功能相同,使用正负号来表示正负数。

    # awk 'BEGIN{printf "%+d
    %+d
    ",1,-1}'
    +1
    -1

    #:换一种表示形式,例如在八进制前加上“0”,在十六进制前加上“0x”。

    # awk 'BEGIN{printf "%#o
    %#x
    ",8,16}'
    010
    0x10

    0:数字0,当需要使用空格填充时以零代替,针对数字。0只会在确保不会改变数字值大小的情况才使用。

    # awk 'BEGIN{printf "%05d
    ",3}'
    00003
    # awk 'BEGIN{printf "%-05d
    ",3}'
    3    # 在左对齐情况下,如果在数字3的右边补齐0会改变数字值大小。

    ':单引号。当系统的区域设置(locale)支持时,可以以千分位表示法表示。这里需要注意为了使单引号修饰符正确被解释,原本awk的单引号用双引号替代,原本printf的双引号使用反斜线转义。

    # awk 'BEGIN{printf "%d
    ",1000000000}'
    1000000000
    # awk "BEGIN{printf "%'d
    ",1000000000}"
    1,000,000,000
    # LC_ALL=C awk "BEGIN{printf "%'d
    ",1000000000}"
    1000000000

    .prec:一个小数点后面跟着一个非负整数来表示精度(precision),不同的控制字符下精度有不同的含义。

    %d, %i, %o, %x, %X:至少打印多少个数字。不够以0填充,超出没事。

    # awk 'BEGIN{printf "%.5d
    ",300}'
    00300
    # awk 'BEGIN{printf "%.5d
    ",300000}'
    300000

    %e, %E, %f, %F:小数点后保留多少位小数。超出则取近似值,不够则以0填充。

    # awk 'BEGIN{printf "%.3f
    ",3.1415926}'
    3.142
    # awk 'BEGIN{printf "%.9f
    ",3.1415926}'
    3.141592600

    %s:指定最长字符宽度,超出部分丢弃。

    # awk 'BEGIN{printf "%.3s
    ","alongdidi"}'
    alo
    # awk 'BEGIN{printf "%.3s
    ","a"}'
    a

    %g, %G:最大有效数字位数(整数+小数)。超出部分会丢弃,如何判断丢弃的部分取决于如何丢弃会使得结果更接近于原值。

    # awk 'BEGIN{printf "%.3g
    ",3.1415926}'
    3.14
    # awk 'BEGIN{printf "%.3g
    ",333.14}'
    333
    # awk 'BEGIN{printf "%.3g
    ",33333333.14}'
    3.33e+07

    sprintf

    printf将格式化后的结果输出而sprintf将格式化后的结果返回。因此可以将返回值赋值给变量或者使用print将返回值输出。

    sprintf是一个字符串函数。

    # awk 'BEGIN{sprintf("%s","alongdidi")}'
    # awk 'BEGIN{print sprintf("%s","alongdidi")}'
    alongdidi
    # awk 'BEGIN{a=sprintf("%s","alongdidi");print a}'
    alongdidi

    重定向输出

    awk支持四种重定向输出。

    1、覆盖重定向输出至文件。

    print[f] "something" > "filename"

    类似于bash中的覆盖重定向。如果文件不存在则创建,如果文件存在的话则先清空原文件的数据再重定向数据。

    对于同一个文件,awk只在首次操作文件时才将其打开。因此,该重定向会将随后的数据追加至文件,这和bash的覆盖重定向机制不同。

    # ls -l name.txt
    ls: cannot access name.txt: No such file or directory
    # awk 'NR>1{print $2 > "name.txt"}' a.txt 
    # cat name.txt 
    Bob
    ... ...
    Bruce    # 除了第一个$2,后续的每一个$2都是以追加的形式。

    2、追加重定向输出至文件。

    print[f] "something" >> "filename"

    与覆盖重定向的区别在于,当文件存在时,追加重定向不会清空文件,每一条记录都追加。

    # cat redirection.txt
    abc
    def
    #    上面是测试文件,自行尝试执行对比区别。
    awk 'BEGIN{for(i=1;i<=3;i++){print "alongdidi">>"redirection.txt"}}'
    awk 'BEGIN{for(i=1;i<=3;i++){print "alongdidi">"redirection.txt"}}'

    3、通过管道重定向输出其他命令。

    print[f] "something" | shellCmd

    示例。

    awk 'NR>1{print $2>"name.unsort";cmd="sort>name.sort";print $2|cmd}END{close(cmd)}' a.txt

    4、重定向输出给协程。

    print[f] "something" |& shellCmd

    至于重定向输入,我们在讲解getline时基本都有涉及到了。

    stdin, stdout, stderr

    awk在重定向时可以直接使用/dev/stdin、/dev/stdout和/dev/stderr。

    awk 'BEGIN{print "something OK" > "/dev/stdout"}'
    awk 'BEGIN{print "something OK" > "/dev/stderr"}'
    awk 'BEGIN{getline<"/dev/stdin";print $0}'
    awk 'BEGIN{print "something OK" | "cat >&2"}'

    使用文件描述符重定向数据。

    exec 4<> a.txt    # 为文件a.txt分配一个文件描述符4
    awk 'BEGIN{while(getline<"/dev/fd/4"){print}}'    # 从文件描述符4中读取数据
  • 相关阅读:
    UMLChina-我不经意的创业故事
    oracle management server
    关于做PDF的FAQ(一)~(四)
    关于学习ASP和编程的28个观点
    JavaScript的方法和技巧
    在公告栏里加进啦Google自定义搜索引擎(附代码,和参考代码,原代码)
    来北京工作了,有写感慨
    asp.net 2.0 访问oracle
    利用SharpZipLib进行文件的压缩和解压缩
    软件工程师,请不要做浮躁的人
  • 原文地址:https://www.cnblogs.com/alongdidi/p/awkOutput.html
Copyright © 2011-2022 走看看