zoukankan      html  css  js  c++  java
  • awk知识点总结

    find+xargs+grep+sed+awk系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html


    0.学习资料推荐

    1.awk入门:看视频、找博客或者看《AWK程序设计语言》的第1-3章。

    2.awk进阶:《awk程序设计语言》剩余内容(剩余的我也没看过,哈哈),man awk

    3.awk编程语言:用于掌控awk的语法和方方面面,推荐书籍《gnu awk: Effective AWK Programming

    1. awk简介和基本语法格式

    Awk自动地搜索输入文件,并把每一个输入行切分成字段。许多工作都是自动完成的,例如读取每个输入行、字段分割、存储管理、初始化等。在AWK中不需声明变量数据类型,它内置字符串类型和数值类型。

    一般来说,在CentOS上安装的awk默认是gawk。它的调用格式为:

    awk [OPTIONS] -f program_file [--] filename_list
    awk [OPTIONS] [--] program filename_list
    

    program是awk程序的重中之重,称为awk的程序,它的格式为PATTERN{ACTIONS}。awk每读入一行,都会先与PATTERN做匹配比较,当找到符合条件的数据就执行对应的ACTION。

    其中PATTERN或ACTIONS二者可省一。省略PATTERN时表示对所有行都执行ACTIONS,省略ACTIONS表示对符合条件的行执行默认的print动作。因为二者可省一,所以用大括号{}将ACTIONS部分包围起来,以区分PATTERN和ACTIONS。

    一个简单的例子,输出/etc/passwd中用户shell为/bin/bash的用户名,其中使用"-F"选项指定冒号作为分隔符。

    awk -F':' '$7 == "/bin/bash"{print "who use bash shell: ",$1}' /etc/passwd
    

    其中位置变量$1,$2...为该行的第几个字段,"$0"表示整行。

    如果要输出多个字段,则字段之间使用逗号","分隔,例如{print $1,$5}但输出时,仍默认以空格分隔各输出字段。

    如果action为print $1 $5,则结果会将"$1"和"$5"拼接在一起,因为空格是awk中的拼接字符。例如变量赋值name = "abc" "bcd"等价于name="abcbcd"。其实不算是拼接符,而是因为awk会忽略任何不被引号包围的空白。

    2.print和printf格式化输出

    awk使用print和printf输出数据,不仅可以输出到标准输出中,还可以重定向到文件中,使用管道传递给另一个命令。

    1. print
      将 $0 打印到标准输出。等价于print $0
    2. print expression, expression, …
      打印各个 expression, expression 之间由 OFS 分开, 由 ORS 终止
    3. print expression,expression,… > filename
      文件名filename必须使用双引号包围,否则被当作变量。且文件只会被打开一次。
    4. print expression,expression,… >> filename
    5. print expression,expression,… | command
      将数据传递给系统命令。命令需要使用双引号包围。
    6. printf(format,expression,expression,…)
    7. printf(format,expression,expression,…) > filename
    8. printf(format,expression,expression,…) >> filename
    9. printf(format,expression,expression,…) | command
    10. close(filename), close( command)
      断开 print 与 filename (或 command) 之间的连接
    11. system(command)
      执行 command; 函数的返回值是 command 的退出状态

    如果print或printf的参数列表中含有操作符,则需要使用括号包围,否则容易产生歧义。如:

    print($1, $3) > ($3 > 100 ? "bigpop" : "smallpop")
    print $1, ($2 > $3) 
    

    执行系统命令的方式,可以通过管道的方式,也可以通过system()函数。注意包围命令的引号加的位置。

    awk 'BEGIN{name="ma long shuai";print (1,2,3,4) | "echo " name}'
    awk 'BEGIN{while (("fdisk -l" | getline) >0){print $0}}'
    awk 'BEGIN{system("fdisk -l")}'
    awk 'BEGIN{name="ma long shuai";system("echo " name)}'
    

    printf命令可以输出更格式化的数据。

    printf(format, value1, value2, ... , valueN)
    

    format是一个字符串,包含按字面输出的纯文本,还包含输出格式,格式使用格式说明符"%"描述,后面跟着几个字符,这些字符控制一个value的输出格式。第一个"%"描述value1的输出格式,第二个"%"描述value2的输出格式,依次类推。因此,"%"的数量应该和被输出的value数量一样多。

    例如:

    { printf("total pay for %s is $%.2f
    ", $1, $2 * $3) }
    { printf("%-8s $%6.2f
    ", $1, $2 * $3) }
    

    第一个程序包含了两个要格式化的value,分别是"$1"和"$2 * $3"。这两个value的输出格式分别被"%s"和"%.2f"描述,前者表示按字符串格式输出"$1",后者表示按小数值格式输出"$2 * $3",且小数位占2位。由于printf不自带尾随换行符,因此手动加一个换行符" "。

    第二个程序,"%-8s"表示"$1"按字符串格式输出,但短横线"-"表示要左对齐输出,"8"表示占用8个字符宽度,不足之数在右边空格补齐。"%6.2f"表示按小数格式输出"$2 * $3",且小数位占用2位,总字符数占用6位。注意,小数点也占用一个字符宽度。因此,一个可能的输出值为"123.20"。

    格式说明符"%"后可跟以下几个常见字符:

    • 格式符:
      • %d,%i:十进制整数;
      • %f:显示浮点数;
      • %s:显示字符串;
      • %u:无符号整数;
      • %%:显示%自身。
    • 修饰符:
      • N:显示宽度;N为数值,宽度不足时若为左对齐则右边空格补足,若右对齐则左边空格补足。
      • -:左对齐;
      • +:显示数值正负号。
      • 0:表示以0填充。

    3.输入行的字段分隔符和行分隔符

    使用"-F"选项或设置内置变量"FS"可以控制输入行的字段分隔符,默认分隔符为" "。可通过正则表达式指定分隔符,其实可以认为总是以正则方式指定分隔符。

    以下是几个示例和需要注意的空格分隔符:

    1. -F " ":默认会压缩所有前导空白,包括制表符和空格。
    2. -F " :":当空格后跟一个冒号时作为分隔符。会压缩前导空格,但不会匹配制表符,更不会压缩制表符。
    3. -F "[ ]':只表示一个空格,不压缩任何空白。
    4. -F "|":指定竖线作为分隔符。
    5. -F ",[ ]*|[ ]+":逗号后跟0或多个空白,或者只有1或多个空白时作为分隔符。

    也就是说,当空格写在最前面且不被中括号包围限制的时候,总会忽略前导空格,但不一定能匹配制表符。

    使用内置变量"RS"可以控制输入行的行分隔符,默认为" ",只有遇到行分隔符时才作为"一行"记录被读取。

    将其读作行分隔符不标准,应该读为"记录分隔符"。例如设置以制表符作为记录分隔符。

    RS="	"
    

    记录分隔符变量"RS"只识别第一个字符,若设置为" ",则第二个" "被忽略。但是控制输出记录分隔符的内置变量OFS则可识别多字符。

    可通过设置FS=" ";RS=""使得awk能处理多行记录。但此时,原本的每行数据整体变成一个字段。

    4.BGEIN和END

    BEGIN和END是一个特殊的PATTERN,BEGIN引导的程序是在awk读取第一个文件第一行前要执行的awk程序,END引导的程序是在awk处理完最后一个文件最后一行后要执行的awk程序。通常BEGIN用于输出一个标题,或者初始化一些格式、变量等,END则用于最后的总结性输出。

    所以awk稍微完整一点的格式为:

    BGEIN{ACTIONS}PATTERN{ACTIONS}END{ACTIONS}
    

    刨去BEGIN和END引导的两个程序,中间处理输入文件的程序PATTER{ACTIONS}称为"主输入循环(main input loop)"。在进入主输入循环之前,可以不用提供输入流,但进入主输入循环后,必须提供输入流。

    例如,在开始处理文件前,设置输出报表的头部,在最后输出总共输出了多少行。其中print ""表示输出一个空行。

    BEGIN{print "ID NAME GENDER GENDER";print ""}{print $0}END{print "total num: " NR}
    

    5.数组

    awk的数组和shell的数组类似,都支持数值index的普通数组和字符串index的关联数组,其实数值index仍然会转换成字符串格式的index,所以awk的数组类型都是关联数组。

    数组格式:array_name[index]
    数值赋值:array_name[1]=value1
    引用数组:array_name[1]

    需要注意的是,关联数组的index必须使用双引号包围,例如array_name["ma"],如果写成array_name[ma],则表示使用变量"ma"的值作为index。若"ma"变量未定义,则这会定义一个新的数组array_name[""]

    使用index in array_name的方式可以判断数组array_name中是否有index下标对应的数组元素。如果有,它会返回1,否则返回0。所以判断语句可以如下:

    if ( "ma" in array_name )
    

    其实,判断某个数组变量的值是否为空也可判断该数组元素是否存在,如下。但这有副作用,当该元素不存在时,会创建它。

    if ( array_name["ma"] != "" )
    

    for循环的一种变体:

    for (i in array_name){
        do something about array_name[i]
    }
    

    可以用于遍历数组,其中变量"i"是遍历数组时的index,array_name是数组名。这是以遍历index的方式遍历数组。由于index的顺序随机,所以遍历时顺序也是随机的。当然,遍历数组的方式有多种,以上只是for循环遍历的一种方式。

    使用delete语句可以删除数组中的元素或者删除整个数组。如下:

    delete array_name["ma"]  # 删除array_name中下标为ma的元素
    delete array_name        # 删除数组array_name
    

    6.流程控制语句

    在ACTION中,可以使用流程控制语句。包括但不限于:

    if (expression) statements
    if (expression) statements else statements
    while (expression) statements
    for (expression; expression; expression) statements
    for (expression in array) statements
    do statements while (expression)
    

    还有几个能影响循环的动作:

    break:退出循环。
    continue:退出当前循环,进入下一个循环
    next:读入下一行,并awk程序的顶端从头开始。这个awk程序是PATTERN{action}这部分,不包括BEGIN{action}exit code:直接进入END,若本就在END中,则直接退出awk。如果END中的exit没有定义code,则采用前一个exit的code。
    

    6.1 条件判断语句

    if格式:

    PATTERN {
      if (test_cmd){
          cmd1
          cmd2
          ...
      }
    }
    

    if-else格式为:

    PATTERN {
       if (test_cmd){
          cmd1
          cmd2
          ......
          }
       else
          cmd3
    }
    

    当if或else结构中的命令只有一个,则其内可省大括号,如果超过一个,则需要使用大括号。

    若采用一行书写格式,则如下:

    PATTERN {if (test_cmd){cmd1;cmd2;...}else {cmd3;cmd4...}}
    

    还有if-else if-else格式。

    PATTERN {
        if (test_cmd){cmd_list1}
        else if {cmd_list2}
        else if {cmd_list3}
        else {cmd_list}
    }
    

    还支持多目操作符。

    expression ? action1 : action2
    

    其中"?"和":"还可以继续嵌套。

    6.2 while循环

    结构:

    PATTERN {
      cmd1
      while (test_cmd)
          cmd
    }
    

    当cmd有多个时,使用大括号包围。

    PATTERN {
        cmd1
        while (test_cmd){
            cmd2
            cmd3
            ....
        }
    }
    

    一行书写格式:

    PATTERN{cmd1;while (test_cmd){cmd1;cmd2}}
    

    6.3 do循环

    和while循环类似,地位和shell中的until循环一样。都是至少执行一次命令列表。

    结构:

    PATTERN {
        do{
            cmd1
            cmd2
        } while (test_cmd)
    }
    

    6.4 for循环

    结构大致如下:

    PATTERN {
        for (i=1;i<=10;++i){
        cmd1
        cmd2
        }
    }
    

    for后括号中包括:变量初始值,条件判断和计数器增长表达式。

    7.更完整的awk程序格式和表达式

    更完整的awk程序的语法格式有以下几种:

    BEGIN{actions}
    END{actions}
    expr{actions}
    /regexp/{actions}:可被regexp匹配的行才执行actions
    expr1,expr2{actions}:表示范围,从满足expr1的行开始,到满足expr2的行结束
    

    其中:

    • expr是表达式。
      • 比较操作符有:< <= == != >= > ~ !~
      • 算术操作符有:+ - * / % ^(取幂) **(取幂)。其中**非POSIX标准,不可移植。
      • 赋值操作符有:++ -- += -= *= /= %= ^= **=。awk支持复合赋值,例如FS = OFS = " "表示字段分隔符和输出字段分隔符都被赋值为制表符。
    • /regexp/为正则匹配模式,表示该行能被regexp匹配则为真。还有以下两种匹配表达式,分别表示给定的字符串能(不能)匹配就为真。
      • string ~ /regexp/
      • string !~ /regexp/
    • 还有复合模式的表达式。使用逻辑操作符"&&"、"||"和"!"连接。如$4 == "Asia" && $3 > 500! (NR > 1 && NF > 3)

    awk中字符串和数值数据类型是自动转换的。如果想要得到一个字符串值,可以value ""进行转换,同理,如果想要得到一个数值,可以value + 0

    另外,正则表达式可以不用包围在两个斜杠中。可以将正则表达式赋值给一个变量,然后使用该变量取匹配数据。例如:

    reg="^[0-9]+$"
    $2 ~ reg
    

    甚至直接使用双引号替换斜杠也允许。但不建议使用,因为一个元字符可能需要多个反斜杠来保护,使得看上去极其晦涩。

    8.awk中的变量

    普通变量:给变量赋值时,如果要赋值字符串,则该字符串应该使用双引号包围,特别是包含特殊字符时。赋值数值时无所谓。 字段变量:$1,$2,$3,...,$NF,还有"$0"表示整行内容。另外,可以直接赋值一个新字段或修改字段值。但这都会影响"$0"。同理,修改"$0"也会影响各字段值。
    内置变量:其实可以分为两类,一类是awk内部自动修改的变量,如行数变量NR,一类是内部不会改动的系统变量,如输入字段分隔符变量FS,完全需要手动修改,这类一般都有默认值。

    • ARGV:命令行参数数组。从0开始计数直到ARGC-1。
    • ARGC:ARGV数组元素的个数。
    • FILENAME:当前处理的文件名。
    • FNR:当前处理文件的记录号。(file record num)
    • NR:已处理的总记录数。多个文件时不重置。(record num)
    • NF:当前记录的字段总数。(field num)
    • FS:输入的字段分隔符。默认为空白。(file separate)
    • OFS:输出的字段分隔符。默认为空白。(output record separate)
    • RS:输入流的记录分隔符。默认为" "。(record separate)
    • ORS:输出流的记录分隔符。默认为" "。(output record separate)
    • OFMT:printf输出数值转换成字符串输出时的格式。默认为"%.6g"。
    • CONVFMT:printf输出数值转换成字符串输出时的格式。会被OFMT覆盖。默认为"%.6g"。
    • RLENGTH:被match函数匹配的字符串的长度。
    • RSTART:被match函数匹配的字符串的开始位置。
    • SUBSEP:下标分隔符。默认为"34",ASCII中034代表的是双引号'"'。

    注意,像NR、FNR、RS等的对象是记录(record),而非行。只有当RS=" "时,读取了一行才表示读取了一条记录。

    9.awk中的内置函数

    awk有两类内置函数:算术函数和字符串函数。还支持自定义函数。

    算术函数:

    • cos(x):取x的余弦。
    • sin(x):取x的正弦。
    • sqrt(x):取x的平方根。
    • rand():返回一个随机数r,其中0<=r<1
    • srand(x):设置rand()的种子值为x。种子值相同时,rand()的结果相同。可print srand()输出当前种子值。
    • int(x):取x的整数部分。

    因此,要生成一个范围[1,n]的随机数,使用int(n*rand() + 1),要四舍五入一个数值,使用int(x + 0.5)

    随机数的种子值相同时,rand的结果总是相同。如下两次运行结果,两次结果中,前两个rand()值相同,后两个rand()值不同,因为中间使用了srand()重设种子值。

    awk 'BEGIN{print rand();print rand();srand();print rand();print rand();print srand()}'
      0.237788
      0.291066
      0.109925
      0.983692
      1504560578
    
    awk 'BEGIN{print rand();print rand();srand();print rand();print rand();print srand()}'
      0.237788
      0.291066
      0.96322
      0.670495
      1504560604
    

    字符串函数:建议下面的所有regexp都使用"//"包围。

    • index(str1,str2):返回子串str2在字符串str1中第一次出现的位置。如果没有指定str1,则返回0。
    • length(str1):返回字符串str1的长度。如果未给定str1,则表示计算"$0"的长度。
    • substr(str1,p):返回str1中从p位置开始的后缀字符串。
    • substr(str1,p,n):返回str1中从p位置开始,长度为n的子串。
    • match(str1,regexp):如果regexp能匹配str1,则返回匹配起始位置。否则返回0。它会设置内置变量RSTART和RLENGTH的值。
    • split(str1,array,sep):使用字段分隔符sep将str1分割到数组array中,并返回数组的元素个数。如果未指定sep则采用FS的值。因此该函数用于切分字段到数组中,下标从1开始。
    • sprintf(fmt,expr):根据printf的格式fmt,返回格式化后的expr。
    • sub(regexp,rep,str2):将str2中第一个被regexp匹配的字符串替换成rep,替换成功则返回1(表示替换了1次),否则返回0。注意是贪婪匹配。
    • sub(regexp,rep):将"$0"中第一个被regexp匹配的字符串替换成rep,替换成功则返回1,否则返回0。注意是贪婪匹配。
    • gsub(regexp,rep,str2):将str2中所有被regexp匹配的内容替换成rep,并返回替换的次数。
    • gsub(regexp,rep):将"$0"中所有被regexp匹配的内容替换成rep,并返回替换的次数。
    • toupper(str):将str转换成大写字母,并返回新串。
    • tolower(str):将str转换成小写字母,并返回新串。

    关于替换函数sub和gsub,可以在替换字符串rep中使用"&"符号表示反向引用,引用的是整个被匹配的部分。

    awk 'BEGIN{
        print index("banana","na")
        print length("banana")
        print match("banana","na.*")
        print toupper("banana")
        print substr("banana",3)}' 
    3
    6
    3
    BANANA
    nana
    
    awk 'BEGIN{str1="x&x";str2="banana"
            print sub(/a.*n/,str1,str2)
            print str2}' 
    1
    bxananxa
    
    awk 'BEGIN{
        print match("banana",/a.*n/)
        print RSTART,RLENGTH}'
    2
    2 4
    
    awk 'BEGIN{print sprintf("hello %i world %5s","123","abc")}'
    hello 123 world   abc
    
    awk 'BEGIN{
        name="Ma long shuai"
        split(name,myname)
        for (i in myname){
            print myname[i]}
        }'
    Ma
    long
    shuai
    

    纵观上述字符串函数,没有一个函数可以将匹配成功的字符串输出出来。但借助match()和RSTART、RLENGTH可以实现。

    例如,取出"Ma:long:shuai"中的"long"并输出。

    awk 'BEGIN{
        name="Ma:long:shuai"
        if (match(name,/:[^:]*:/)){
            print substr(name,RSTART+1,RLENGTH-2)}}'
    long
    

    10.自定义函数

    function name(parameter-list) {
        statements
    }
    

    函数中的变量不影响函数外的变量,但可以使用外部变量。参数列表使用逗号分隔,这些参数只在函数内部生效。

    可以在awk的引号内任意位置处定义函数(即使是BEGIN之前或END之后),且函数的调用位置可以在函数的定义位置之前。但注意,函数必须不能定义在BEGIN或主输入循环或END内部,否则自定义函数的大括号会和包围action的大括号冲突而报错。即如下(1)-(4)处位置可定义定义函数,在任意位置处调用函数。

    awk '(1)BEGIN{ACTIONS}(2)PATTERN{ACTIONS}(3)END{ACTIONS}(4)'
    

    在函数的statements中,可以使用return expression语句,表示函数的返回值。

    例如,创建一个"向字符串指定位置处插入一个字符"的函数。

    awk 'function insert(STRING, POS, INS) {
        before_tmp = substr(STRING, 1, POS)
        after_tmp = substr(STRING, POS + 1)
        return before_tmp INS after_tmp
    }
    BEGIN{print insert("banana",3,"x")}'
    

    11.getline函数

    getline函数用于从文件、标准输入或管道中读取数据,并按情况设置变量的值。getline可以自动不断的加载下一行。如果能读取记录,则getline的返回值为1,遇到输入流的尾部时,返回值为0,不能读取记录(如文件没有读取权限、文件不存在)时,返回值为“-1"。

    其中:

    • getline:会从主输入文件中读取记录。会同时设置$0,NF,NR,FNR。
    • getline var:会从主输入文件中读取记录,并将读取的记录赋值给变量var。会同时设置var,NR,FNR。
    • getline <file:从外部文件file中读取记录。同时会设置$0,NF。
    • getline var <file:从外部文件file中读取记录,并将读取的记录赋值给变量var。会同时设置var。
    • cmd | getline:从管道中读取记录。会同时设置$0,NF。
    • cmd | getline var:从管道中读取记录,并将读取的记录赋值给变量var。会同时设置var。

    也就是说:

    1. 当getline从非主输入文件读取记录时,不会设置NR和FNR;
    2. 当getline后没有给定变量var时,会将读取的记录赋值给$0,于是会同时设置NF并切分成字段;否则将读取的记录赋值给变量var,不会设置NF切分字段。

    仍然注意,从外部文件file中读取记录时,需要使用双引号包围文件名,否则被当成awk中的变量。

    例如,执行Linux下的who命令并传递给getline读取,每读取一行记录,变量n自增1。

    while ("who" | getline)
    n++
    

    将Linux命令date的结果保存到awk的变量date中。

    "date" | getline date
    

    当写成循环时,如:

    while (getline <"file"){
        cmd...
    }
    

    这是不安全的,因为当无法读取file时,返回值为"-1",而while循环的判断条件是0和非0,所以"-1"也会进入死循环。所以,安全的写法为:

    while (getline <"file" >0){
        cmd...
    }
    

    12.向awk传递变量

    awk很重要且必备的能力是接受外界的变量,例如shell中的变量,shell中命令执行的结果,或者是在开始执行awk前应该初始化的变量。

    例如,在shell中定义一个变量name,传递给awk使用。

    awk -v awk_name="$name" 'BEGIN{print awk_name}' 
    Ma longshuai
    

    有三种方式可以向awk传递变量:

    1.将待传递变量当作文件名被awk解析。awk识别后发现是赋值语句,就认为其是变量传递。变量赋值语句必须定义awk program之后。此法定义的变量不可在BEGIN中使用,因为它是被当成文件解析的,只有在需要读取主输入文件的时候才会被解析。

    awk 'BEGIN{}PATTERN{print var1,var2,var3}' var1=value1 var2=value2 file1 var3=value3 var1=value4 file2
    

    在上面的语句中,当awk执行完BEGIN程序后,准备读取主输入,于是开始解析program后的输入文件。解析时发现,var1和var2都是赋值语句,于是当成变量处理,当读取到file1时,发现只有一个参数,则当作输入文件,于是开始处理该文件。在处理file1时,var1和var2都是有效的,但var3还未赋值,因此var3无效。当处理完file1后,继续解析下一个主输入文件,此时var3被赋值,并开始处理file2。在处理file2时,var1、var2和var3都是有效的,但var1被新值覆盖。

    此外,还可以将shell命令的结果赋值给这些预定义变量。如下展示了几种变量定义的方式:

    name="Ma longshuai"
    awk 'program' OFS=":" var1="$name" var2="`echo Ma longshuai2`" var3="Ma longshuai3" var4=Malongshuai4 filename
    

    不仅可以定义普通变量,还可以定义内置变量(如上OFS)。注意加引号的方式:为了安全,应该对所有赋值语句的value部分加上双引号,除非所赋的值不包含特殊字符。所以,如果上面的var1赋值语句写成var1=$name,将被awk解析成var1=Ma longshuai,于是var1的值为Ma,主输入文件为longshuai。

    2.使用"-v"选项传递。变量赋值语句必须定义在awk program之前。这种方法定义的变量可以在BEGIN程序中使用。

    除了定义在program之前,定义方式同上。每定义一个变量,都需要使用一个"-v"选项。如:

    name="Ma longshuai"
    awk -v OFS=":" -v var1="$name" -v var2="`echo Ma longshuai2`" -v var3="Ma longshuai3" 'program' filename
    

    3.通过参数数组ARGV的方式。

    ARGV是内置的数组变量。awk内部会将命令行切分,并按规则将各参数存放到ARGV数组中,数组下标从0开始,这是awk中唯一下标从0开始的数组。在存放到ARGV时,所有的选项和program会被忽略。

    每存储一个数组变量,特殊变量ARGC的值增加1。因此ARGC的值代表的是参数的个数。所以,数组变量从ARGV[0]到ARGV[ARGC-1]。

    可使用类似下面的循环来遍历ARGV数组。

    awk -F "	" -v var1="value1" 'BEGIN{
            for(i=0;i<ARGC;++i){
                print "ARGV[" i "]: " ARGV[i]
            }
            print "ARGC: " ARGC
        }' "a" "b" "v=1" file 
      ARGV[0]: awk
      ARGV[1]: a
      ARGV[2]: b
      ARGV[3]: v=1
      ARGV[4]: file
      ARGC: 5
    

    注意,ARGV[0]存储的是awk命令,"-F"和"-v"选项都没有存储到ARGV中。

    ARGC和ARGV数组变量的值都可以手动修改。命令行分割存储完成之后,开始处理BEGIN,再处理主循环输入。因此,在BEGIN中修改ARGV中输入文件对应的值,可以改变awk所读取的输入文件,若将其设置为空,则该数组变量直接被跳过,也就不再读取该输入文件。

    需要注意的是,当增加ARGV元素时,必须同时递增ARGC的值,因为awk是根据AGRC来读取ARGV的。同理,只增加ARGC的值,将导致新建ARGV数组元素,且这些新元素的值为空。也因此,如果减小ARGC的值,将导致无法访问超出ARGC-1边界的ARGV元素。

  • 相关阅读:
    AD 快捷键
    AD PCB 错误检查
    AD 在 PCB导出封装库
    AD PCB 机械层 画板步骤
    不同频率对PCB材料的要求
    RF 天线长度,通信距离估算
    RF硬件检查注意事项
    影响RSSI的因素
    阅读与思考
    面向对象特性分析
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/7509812.html
Copyright © 2011-2022 走看看