AWK相关

第五章 gawk


5.1 什么是awk,什么是nawk,什么是gawk?
   awk是Linux/UNIX下用来操纵数据和产生报告的程序语言,Nawk是新的版本,gawk是Gnu的版本。数据可以来自标准输入、一个或者多个文件,或者其他命令的输出。awk可用于命令行的简单操作,也可以写入大的应用程序。因为awk可以操纵数据,所以踏实Shell脚本和管理小型数据库中必需的工具。
   awk逐行扫描文件,从第一行到最后一行,寻找匹配特定模板的行,并在这些行上运行“选择”动作。如果一个模板没有指定动作,这些匹配的行就被显示在屏幕上。如果一个动作没有模板,所有被动作指定的行都被处理。

 

5.1.1 awk的含义
   awk分别代表其作者形式的第一个字母,它的作者是Alfred Aho、Brian Kernighan 和PeterWeinberger。

 

5.1.2用哪一个awk?   
   在很多系统中,awk被连接到正在使用的版本中,在描述awk和其特性是,我们将使用awk命令,假设它已经被连接到gawk上了,就像下面的例子一样。

 

5.2  awk的格式
   一个awk程序包括awk命令、程序结构、引用(或输入文件)和输入文件的名字。如果输入文件没有被指定,输入就来自标准输入或键盘。

   awk结构由模板、动作或者模板和动作联合组成。模板是由某种类型表达式的说明组成。如果没看见关键字if,但是你在评价表达式的时候想到了单词if,这就是模板。动作是在大括号内被分号或者新的一行分隔的一个或者多个说明。模板不能够放在大括弧中,由在斜杠中间的正则表达式和awk提供的操作中的一个或者几个组成。
格式:
% awk 'pattern' filename
% awk '{action}' filename
% awk 'pattern  {action}' filename
例如
# df| awk '$4>75000'

 

5.2.3 awk 命令行选项

 

5.3 格式输出


5.3.2 OFMT 变量


5.4 文件中的awk命令


5.5 记录和域
   awk并不是把输入文件看做一个没有终止的字符串,而是看做具有一定格式和结构的。默认每一个以换行符结束的行称作一个记录。

   记录分隔符 默认输入和输出的分隔符都是回车,保存在awk内建变量ORS和RS中,ORS和RS的值可以在有限的范围内修改。
   $0变量     在awk中$0指的是整条记录(当发生替换或者复制而使得$0的值发生改变时,NF的值和域的个数都跟着发生改变)。换行符的值保存在awk内建变量RS中,默认情况下回车。
   变量NR     多个记录的每一条都保存在内建变量NR中。每处理完一个记录,NR的值就增加1。

 

5.5.2 域
   记录中的每一个单词称作“域”,默认情况下以空格或者tab分隔。每一个单词叫做一个域,awk跟踪域的数量,并在内建变量NF中保存这个数字。每一行的域个数是不一样的,典型限制为每行100个。可以建立新的域。

 

5.5.3 域分隔符
   输入域分隔符 awk的内建变量FS保存输入与分隔符的值。默认值是空格或者tab。可以在BEGIN语句中或者命令行上修改FS的值。
   在命令行上修改域分隔符 awk命令后面加上-F选项可以用来修改输入文件的域分隔符。在-F后面的字符串立刻变成新的饿域分隔符。包含元字符的字符串可以重新设置多个域分隔符。
   使用多个域分隔符 你可以指定多个输入分隔符,若域分隔符有多个字符组成,如FS,则该字符串是一个放在方括号内的正则表达式。
   输出域分隔符 默认的输出分隔符是一个空格,保存在awk的内建变量OFS中。逗号用来分隔print的域,就是OFS中的值。

 

5.6 模式与动作


5.6.1 模式
   awk模式控制awk对输入的文件行所做的动作。一个模式包括正则表达式、条件表达式,或者二者的结合。当条件表达式为真的时候,默认动作是打印该行。当读取一个模式表达式时,可以使用if语句。使用if时不需要花括号引用。这里的if变成一个动作语句,语法结构发生了变化。


5.6.2 动作
   花括号内的,用分号分隔的语句称为动作。如果模式在动作前面,模式决定什么时候发出动作。动作可以使一个语句也可以是一组语句。语句之间用分号分隔,也可以用换行符。


5.7  正则表达式
   对于awk来说,正则表达式就是由斜杠之间的字符组成的模式。awk支持用正则表达式元字符修改正则表达式。

   POSIX字符集  POSIX(the ProtableOperating SystemInterface)是一个用于保证程序在不同的平台之间移植的工业标准。为了便于移植,POSIX重新组织了字符集,其中包括不同国家和地区的字符、编码、用于表示现金、时间以及日期的符号等等。为了处理不同类型的字符,POSIX把表5.7中用的方括号引用的字符集的类加入了基本和扩展的正则表达式中。
   例如,类[:alnum:]是A-Za-z0-9的另外一种表示方法。要使用这个类,必须将其放在另外一对方括号中,以重新组织成一个正则表达式。

 

5.7.1 匹配操作符
   匹配操作符(~)用来在记录或者域内匹配正则表达式。

 

5.8 脚本文件中的awk命令
   当你有多个awk的模式/动作语句的时候,最简单的办法就是把他们放在一个脚本文件中。脚本文件是一个包含awk注释和语句的文件。如果语句和动作在同一行,则必须分号分隔。若在不同的行则无需使用分号了。如果模式后面是动作,左花括号就必须与模式在同一行。


第六章
gawk功能:给表达式赋值


6.1.1比较表达式
   比较表达式匹配那些只在条件为真时才运行的行。这些表达式利用关系运算符来比较数字和字符串。
<, <=, ==, !=, >=,>, ~(匹配正则表达式:x~/y/),!~(不匹配正则表达式:x!~/y/)

 

6.1.2 条件表达式
   条件表达式使用两个符号——问号和冒号给表达式赋值。这里有一个更简洁的方法,他能实现if/else
语句一样的效果。标准格式如下:
    conditionalexpression1 ? expression2 : expression3
   这个格式跟下面的if/else语句产生的结果是一样的
{
  if(expression1)
   expression2
  else
   expression3
}

 

6.1.3 运算
   运算可以在模板内进行。awk把所有的运算都作为浮点运算。
, -, *, /, %(取余),^(乘方)

 

6.1.4 符合模板
   符合模板是用逻辑运算符连接在一起的由模板组成的表达式,且该表达式从左到右赋值。
&&, ||, !

 

6.1.5 范围模板
   范围模板匹配从第一个模板的第一次出现到第二个模板的第一次出现,第一个模板的下一次出现到第二个模板的下一次出现等等。如果第一个模板被匹配而第二个模板没有出现,awk就显示到文件末尾的所有行。

 

6.1.6 数据验证程序


第七章 gawk功能:gawk编程
7.1.1 数字和字符串常量
   初始化和类型强制 在awk中,变量不需要定义就可以直接使用,使用一个变量就是对变量的定义。变量的类型可以试数字、字符串,或者两者都有。在赋值的时候,等号又变表达式的类型就是变量的类型。
   根据使用的不同,未初始化的变量的值为0或者空白字符串“”
   强制字符串转换为数字:

   强制数字转换为字符串:

   所有split函数建立的域和数组元素都被认为是字符串变量,除非它值包含数字值,如果域或者数组元素为空(null),那么它们的值就是null。一个空行也被看作是一个空的字符串。

7.1.2 自定义变量
   自定义变量由字母、数字和下划线组成,但是不能以数字开头。awk中的变量不需要声明。awk根据表达式中变量的内容来确定变量的类型。如果变量没有初始化,awk就初始化字符串变量的值为NULL,数值变量值为0。如果有必要,awk能把数字变量转换为字符串变量,或者相反。变量通过复制符号被赋值。

   递增和递减操作符
   命令行自定义变量 可以在命令行中给变量赋值,然后再把这个变量传输给awk脚本。
    例如,# awk -F:-f awkscript month=4 year=2000filename    注:变量定义要在filename前面
   -v选项(awk)。awk的-v选项允许BEGIN语句处理命令行参数。对于每一个从命令行传输的参数,他们前面都必须有-v选项
   域变量域变量的用法类似于自定义变量,只是域变量引用的域不同。新的域可以通过赋值建立。一个域如果已被参考但是还没有赋值,它的值就是空字符串。一旦与的值改变了,就是用当前作为域分隔符的OSF的值重新计算$0变量。通常域的总数限制在100以内。
    例如,# awk '$4== "CA" { $4 = "California"; print}' filename
   如果第四个域的值($4)等于CA,awk就把第四个域赋值为"California"。注意,一定要有双引号,否则系统就会误认为是自定义变量而赋值为NULL.
   内建变量 内建变量的名字是由大写字母组成。它们事先被赋值并可以在表达式中使用。 
                      
                   内建变量清单
   变量名                     变量内容
    ARGC                      命令行参数的数量
    ARGIND                    命令行正在处理的当前文件的AGV的索引(仅在gawk中有效)
    ARGV                      命令行参数数组
    CONVFMT                   转换数字格式(仅在gawk中有效),默认是%.6g
    ENVIRON                   从shell传递来的包含当前环境变量的数组
    ERRNO                     当使用close函数或者通过getline函数读取的时候,发生的重新定向错误

                                的描述信息就保存在这个变量中
    FIELDWIDTHS               在对记录进行固定域宽的分割时,可以替代FS的分隔符的列表
    FILENAME                  当前的输入文件名
    FNR                       当前文件的记录号
    FS                        输入域分隔符,默认是空格
    IGNORECASE                在正则表达式和字符串操作中关闭大小写敏感
    NF                        当前文件域的数量
    NR                        当前文件的记录数
    OFMT                      数字输出格式
    OFS                       输出域分隔符
    ORS                       输出记录分隔符
    RLENGTH                   通过match函数匹配的字符串的长度
    RS                        输入记录分隔符
    RSTART                    通过match函数匹配的字符串的偏移量
    RT                        记录结束符在输入文本的时候,gawk把它设为与RS相同
    SUBSEP                    下标分隔符

7.1.3 BEGIN 模块
   BEGIN模块后面紧跟着动作块,这个动作块在awk处理任何输入文件行之前执行。事实上,BEGIN块可以在没有任何输入文件的条件下测试,因为在BEGIN块执行完毕以前awk不读取任何输入文件。BEGIN块通常被用来改变内建变量的值,例如OFS,RS及FS等等。

7.1.4 END模块
   END模块不匹配任何输入文件,但是执行动作块中的所有动作。END模块在整个输入晚间处理完毕后被处理。

7.2  重新定向和管道
7.2.1 输出文件的重新定向
   重新定向awk的输出到一个UNIX文件,需要使用Shell重新定向符,文件名必须被双引号括起来。
7.2.2 输入重新定向(getline)
    getline函数。getline函数的作用是从标准输入、管道或者当前正在处理的文件之外的其他输入晚间获得输入。它负责从输入获得下一行的内容,并给NF、NR和FNR等内建变量赋值。如果得到一个记录,getline函数就返回1,如果倒到文件的末尾就返回0。如果出现错误,例如打开文件失败,就返回-1。

7.3 管道
   如果你在awk程序中打开一个管道,那么在打开下一个管道之前必须关闭它。管道符号右边可以通过双引号关闭管道。在同一时刻只能有一个管道存在。

7.4 关闭文件和管道
   如果你打算在awk程序中再次使用文件、管道来进行读或者写,则先要去关闭它,因为知道脚本结束它都不会自动关闭。一旦打开,管道就保持开的状态知道awk退出。所以END模块中的语句对于管道也是有效的,END模块的第一行语句就是关闭管道。
   system函数。内建的system函数把Linux命令作为参数执行这些命令,然后返回退出状态值给awk程序。这有一点像C标准中的system()函数。Linux的命令必须被双引号引用。如果system的参数是一个空字符串,那么输出缓冲区就被刷新。
    例如,{
           system( "cat" $1 )
           system( "clear" )
         }
   fflush函数。用来刷新输出缓冲区。如果没有参数,fflush函数就刷新标准的输出的缓冲区。如果fflush的参数是空字符串,例如fflush(""),fflush就帅新所有文件和管道的输出缓冲区。

7.6 条件语句
if/else else if

7.7循环
while for

7.8 程序控制语句
7.8.1 next 语句
   next语句从输入文件中读取下一行,然后从头开始执行awk脚本。
    例如(InScript)
{
  if ( $1 ~ /Peter/){next}
  else {print}
}
7.8.2 exit 语句
   exit语句用于结束awk程序。它终止对记录的处理,但是不会略过END模块,如果exit语句被赋予一个0~255之间的参数(例如exit 1),这个参数就被打印到命令行,以判断退出成功还是失败。
例如(In Script)
   {exit(1)}
(The Command Line)
# echo $status (csh,tcsh)
1
# echo $?(bash,sh,ksh,tcsh)
1


7.9 数组
   因为awk中数组的小标可以试数字和字母,所以称为关联数组(associativearray)。数组的下标(subscript)通常称为关键字(key)并且跟相应元素的值有关系。值和关键字都存储在内部的一张对问题中的关键字和值应用散列运算法则的表格里(也就是哈希表)。由于在哈希表中使用的技术,数组元素不是按照顺序存储的。如果显示数组的内容就会发现,它们并不是按照你预料的顺序显示出来的。
    数组跟变量一样,都是在使用的时候自动创建,awk可以自己判断其存储的是数字还是字符串。根据内容的不同,awk的数组初始值是数字0或空字符串。你不需要声明awk数组的大小。awk数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

7.9.1 下标与关联数组
   用变量作为数组索引。 变量可以作为数组下标值的索引,该变量的值可以试数字或者字符串。
   special for循环。  special for循环在for循环一旦无法发挥作用的时候,用于循环读取关联数组中的元素。当下标是字符串或者是不连续的数字时,specialfor循环把下标作为关键字访问跟其关联的值。
   用字符串作为下标。下标可以试文字或者包含字符串的变量。如果下标是文字,那么必须用双引号括起来。
   用域值作为数组的下标。任何表达式都可以用作数组的下标,域当然也可以。示例7.52中的程序计算所有在第二个域中的名字出现的次数并介绍了一种新的for循环方式。
   for(inde_value in array) statement
   数组和split函数。awk的内建函数split允许你把一个字符串分隔为单词并存储在数组中。你可以自己定义域分隔符或者使用现在FS(域分隔符)的值。
   delete函数。 该函数用于删除数组元素。
   awk的多维数组

7.9.2 awk的命令参数处理
   AGRV。对于awk和gawk来说,可以合法地在命令行上使用内建数组ARGV。这个数组包括命令本身,担不是所有可传递到awk的选项。数组ARGV的索引从0开始。
   ARGC。 ARGC是一个内建的、包含命令行参数个数的变量。awk并不把选项作为参数。

7.10 awk内建函数
7.10.1 字符串函数
   sub和gsub函数。sub函数匹配记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果目标字符串已经指定,正则表达式匹配目标字符串中最大的、最靠左的子字符串,并用替换字符串替换它。如果没有指定目标字符串就默认使用这个记录。
格式:
    sub(regularexpression, subsitution string);
    sub(regularexpression, subsitution string, target string);

gsub函数则使得在所有正则表达式被匹配的时候都发生替换。
    gsub(regularexpression, subsitution string);
    gsub(regularexpression, subsitution string, target string);

   index函数。 inedex函数返回子字符串第一次被匹配的位置,偏移量从位置1开始。
格式:
   index(string, substring)
例如:
# awk '{ print index("hollow", "low")}' filename
4
说明:返回子字符串low在hollow中的位置,偏移量从1开始。

   length函数。length函数返回没有参数的字符串的长度。length函数返回整个记录中的字符数。

   stustr函数。substr函数返回从位置1开始的字符串的子字符串。如果子字符串的长度给定,就返回字符串的一部分。如果指定的长度超过实际长度,就返回整个字符串。
格式:
   substr(string, starting position)
   substr(string, starting position, length of string)

   match函数。match函数返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式就返回0。match函数设置内建变量RSTART为字符串中子字符串的开始位置,RLENGTH为到子字符串末尾的字符个数。substr函数可以用这些变量来提取模式(pattern)。
格式:
   match(string, regular expression)
例如:
    # awk'END{start=match("Good ole USA", /[A-Z] $/); print start,RSTART,RLENGTH}' filename
    10 103
说明:
    正则表达式/[A-Z]$/表示在字符串的末尾搜索连续的大写字母。在字符串"Good ole USA"的第十个位置找到字符串“USA”。
如果没有字符串匹配就返回0。

   toupper和tolower函数(仅在gawk中有效)。toupper函数把字符串中所有的小写字母都变为大写,而非字母的字符则不改变。同理,tolower函数把字符串中所有的大写字母都变成小写,而非字母的字符也不改变。
格式:
   toupper(string)
   tolower(string)

   split函数。split函数使用作为第三个参数的域分隔符把字符串分割为一个数组。如果第三个参数没有提供,awk就默认使用当前FS值。
格式:
    split(string, array, field separator)
    split(string, array)

   sprintf函数。springf函数返回指定格式的表达式。这个函数允许你使用printf函数的格式说明符。
格式:
   variable=sprintf("string with format specifiers ", expr1, expr2,..., exprn)

7.10.2 时间函数
   gawk提供了两个分别用来获取时间及格式化时间戳的函数。它们是systime和strftime函数。
   systime函数。systime函数返回从1970年1月1日(称为元年)开始到当前的时间(不计闰年)的整秒数。
格式:
   systime()
 
   strftime函数。strftime函数使用C库中的strftime函数格式化时间。格式说明符的格式是%T或%D等等,时间戳的格式跟systime函数返回值是一样的。如果时间戳被忽略,则默认使用当前时间。

7.10.3 内建数学函数
atan2/cos/exp/int/log/rand/sin/sqrt/srand

7.11 自定义函数
   自定义函数可以放在脚本中任何可以防止模板和动作的地方。
格式:
    functionname ( parameter, parameter, parameter, ...) {
       statements
       retrun expression
     (The return statement and expression are optional )
}
   给函数中本地变量传递值。只使用变量的拷贝。数组通过地址或者指针传递,所以可以在函数内部直接改变数组元素的值。函数内部使用的任何没有作为参数传递的变量都被看做是全局变量,也就是这些变量对于整个程序都是可见的。如果变量再函数中发生了改变,那么就是在整个程序中发生了改变。唯一向函数提供本地变量的办法就是把他们放在参数列表中,这些参数通常被放在列表的最后。如果函数调用的时候没有提供正式的参数,那么参数就初始化为空。return语句通常就返回程序控制并向函数调用者返回一个值。


7.13 其他细节
   从磁带或电子表格中读取的数据也许没有明显域分隔符,但是数据有固定的列宽,可以用substr函数预处理这些数据。

7.13.1 固定的域
   如果域的宽度是固定的,但不是由域分隔符分割的。substr函数用来建立域。
    空域。如果数据保存在固定宽度的域内,那么一些域就可能是空的。在下面的例子中,substr函数用来保存这些域,而无论它们是否含有数据。
   FIELDWIDTHS变量。如果文件中域的宽度固定,则可以使用FILEDWIDTHS变量(仅在gawk中使用)。这个变量的值是以空格分隔的数字列表,列表中的每个数字都表示相应的域的宽度。如果设置了变量FIELDWIDTHS,FS的值就将被忽略。
    例如 # catfixedfile
        abc1245556
        xxxyyyzzzz
        # awk 'BEGIN{FIELDWIDTHS="3 3 4"}{print $2}' fixedfile
        124
        yyy
   有$的数字、逗号和其他符号。在下面的例子中,价格域包含一个美元符号和一个逗号。要计算最后的结果,这些符号必须被去掉。可以用gsub处理这件事情。

7.13.2 捆绑和解捆绑文件
   捆绑程序。在Alfred、Brian Kernifghan和Peter Wienberger共同编写的《AWK ProgrammingLanguage》中,捆绑文件的程序非常短。我们现在准备合并多个文件以节约磁盘空间,或者用电子邮件发送文件等等。
例如,
# awk '{print FILENAME, $0 }' file1 file2 file3 >bundled
    解捆绑。
例如,
# awk '$1 !=previous { close(previous); previous=$1}; \
    {printsubstr($0, index($0, "  ") 1) >$1}' bundled

7.13.3 多行记录
   目前例子中使用的数据文件,每个记录只占用一行。后面的数据文件,叫做checkbook,记录用空行来分隔,域用换行符来分隔。要处理这样的文件,应将记录分隔符RS赋值为空域分隔符FS赋值为换行符。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值