大学校园网站模板图片,网页源码在线提取,盐城做百度网站,苏州设计网站Awk 是一种非常好的语言#xff0c;同时有一个非常奇怪的名称。在本系列#xff08;共三篇文章#xff09;的第一篇文章中#xff0c;Daniel Robbins 将使您迅速掌握 awk 编程技巧。随着本系列的进展#xff0c;将讨论更高级的主题#xff0c;最后将演示一个真正的高级 a…Awk 是一种非常好的语言同时有一个非常奇怪的名称。在本系列共三篇文章的第一篇文章中Daniel Robbins 将使您迅速掌握 awk 编程技巧。随着本系列的进展将讨论更高级的主题最后将演示一个真正的高级 awk 演示程序。捍卫 awk在本系列文章中我将使您成为精通 awk 的编码人员。我承认awk 并没有一个非常好听且又非常“时髦”的名字。awk 的 GNU 版本叫作 gawk听起来非常怪异。那些不熟悉这种语言的人可能听说过 “awk”并可能认为它是一组落伍且过时的混乱代码。它甚至会使最博学的 UNIX 权威陷于错乱的边缘使他不断地发出 “kill -9!” 命令就象使用咖啡机一样。 的确awk 没有一个动听的名字。但它是一种很棒的语言。awk 适合于文本处理和报表生成它还有许多精心设计的特性允许进行需要特殊技巧程序设计。与某些语言不同awk 的语法较为常见。它借鉴了某些语言的一些精华部分如 C 语言、python 和 bash虽然在技术上awk 比 python 和 bash 早创建。awk 是那种一旦学会了就会成为您战略编码库的主要部分的语言。 第一个 awk让我们继续开始使用 awk以了解其工作原理。在命令行中输入以下命令 $ awk ‘{ print }’ /etc/passwd 您将会见到 /etc/passwd 文件的内容出现在眼前。现在解释 awk 做了些什么。调用 awk 时我们指定 /etc/passwd 作为输入文件。执行 awk 时它依次对 /etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout所得到的结果与与执行catting /etc/passwd完全相同。 现在解释 { print } 代码块。在 awk 中花括号用于将几块代码组合到一起这一点类似于 C 语言。在代码块中只有一条 print 命令。在 awk 中如果只出现 print 命令那么将打印当前行的全部内容。 这里是另一个 awk 示例它的作用与上例完全相同 $ awk ‘{ print $0 }’ /etc/passwd 在 awk 中$0 变量表示整个当前行所以 print 和 print $0 的作用完全一样。 如果您愿意可以创建一个 awk 程序让它输出与输入数据完全无关的数据。以下是一个示例 $ awk ‘{ print “” }’ /etc/passwd 只要将 “” 字符串传递给 print 命令它就会打印空白行。如果测试该脚本将会发现对于 /etc/passwd 文件中的每一行awk 都输出一个空白行。再次说明 awk 对输入文件中的每一行都执行这个脚本。以下是另一个示例 $ awk ‘{ print “hiya” }’ /etc/passwd 运行这个脚本将在您的屏幕上写满 hiya。:) 多个字段awk 非常善于处理分成多个逻辑字段的文本而且让您可以毫不费力地引用 awk 脚本中每个独立的字段。以下脚本将打印出您的系统上所有用户帐户的列表 $ awk -F”:” ‘{ print $1 }’ /etc/passwd 上例中在调用 awk 时使用 -F 选项来指定 “:” 作为字段分隔符。awk 处理 print $1 命令时它会打印出在输入文件中每一行中出现的第一个字段。以下是另一个示例 $ awk -F”:” ‘{ print $1 $3 }’ /etc/passwd 以下是该脚本输出的摘录 halt7operator11root0shutdown6sync5bin1….etc. 如您所见awk 打印出 /etc/passwd 文件的第一和第三个字段它们正好分别是用户名和用户标识字段。现在当脚本运行时它并不理想 — 在两个输出字段之间没有空格如果习惯于使用 bash 或 python 进行编程那么您会指望 print $1 $3 命令在两个字段之间插入空格。然而当两个字符串在 awk 程序中彼此相邻时awk 会连接它们但不在它们之间添加空格。以下命令会在这两个字段中插入空格 $ awk -F”:” ‘{ print $1 ” ” $3 }’ /etc/passwd 以这种方式调用 print 时它将连接 $1、” ” 和 $3创建可读的输出。当然如果需要的话我们还可以插入一些文本标签 $ awk -F”:” ‘{ print “username: ” $1 “/t/tuid:” $3″ }’ /etc/passwd 这将产生以下输出 username: halt uid:7username: operator uid:11username: root uid:0username: shutdown uid:6username: sync uid:5username: bin uid:1….etc. 外部脚本将脚本作为命令行自变量传递给 awk 对于小的单行程序来说是非常简单的而对于多行程序它就比较复杂。您肯定想要在外部文件中撰写脚本。然后可以向 awk 传递 -f 选项以向它提供此脚本文件 $ awk -f myscript.awk myfile.in 将脚本放入文本文件还可以让您使用附加 awk 功能。例如这个多行脚本与前面的单行脚本的作用相同它们都打印出 /etc/passwd 中每一行的第一个字段 BEGIN {FS”:”} { print $1 } 这两个方法的差别在于如何设置字段分隔符。在这个脚本中字段分隔符在代码自身中指定通过设置 FS 变量而在前一个示例中通过在命令行上向 awk 传递 -F”:” 选项来设置 FS。通常最好在脚本自身中设置字段分隔符只是因为这表示您可以少输入一个命令行自变量。我们将在本文的后面详细讨论 FS 变量。 BEGIN 和 END 块通常对于每个输入行awk 都会执行每个脚本代码块一次。然而在许多编程情况中可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况awk 允许您定义一个 BEGIN 块。我们在前一个示例中使用了 BEGIN 块。因为 awk 在开始处理输入文件之前会执行 BEGIN 块因此它是初始化 FS字段分隔符变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。 awk 还提供了另一个特殊块叫作 END 块。awk 在处理了输入文件中的所有行之后执行这个块。通常END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。 规则表达式和块awk 允许使用规则表达式根据规则表达式是否匹配当前行来选择执行独立代码块。以下示例脚本只输出包含字符序列 foo 的那些行 /foo/ { print } 当然可以使用更复杂的规则表达式。以下脚本将只打印包含浮点数的行 /[0-9]/.[0-9]*/ { print } 表达式和块还有许多其它方法可以选择执行代码块。我们可以将任意一种布尔表达式放在一个代码块之前以控制何时执行某特定块。仅当对前面的布尔表达式求值为真时awk 才执行代码块。以下示例脚本输出将输出其第一个字段等于 fred 的所有行中的第三个字段。如果当前行的第一个字段不等于 fredawk 将继续处理文件而不对当前行执行 print 语句 $1 “fred” { print $3 } awk 提供了完整的比较运算符集合包括 “”、””、””、””、”” 和 “!”。另外awk 还提供了 “~” 和 “!~” 运算符它们分别表示“匹配”和“不匹配”。它们的用法是在运算符左边指定变量在右边指定规则表达式。如果某一行的第五个字段包含字符序列 root那么以下示例将只打印这一行中的第三个字段 $5 ~ /root/ { print $3 } 条件语句awk 还提供了非常好的类似于 C 语言的 if 语句。如果您愿意可以使用 if 语句重写前一个脚本 {if ( $5 ~ /root/ ) {print $3}} 这两个脚本的功能完全一样。第一个示例中布尔表达式放在代码块外面。而在第二个示例中将对每一个输入行执行代码块而且我们使用 if 语句来选择执行 print 命令。这两个方法都可以使用可以选择最适合脚本其它部分的一种方法。 以下是更复杂的 awk if 语句示例。可以看到尽管使用了复杂、嵌套的条件语句if 语句看上去仍与相应的 C 语言 if 语句一样 {if ( $1 “foo” ) {if ( $2 “foo” ) {print “uno”} else {print “one”}} else if ($1 “bar” ) {print “two”} else {print “three”}} 使用 if 语句还可以将代码 ! /matchme/ { print $1 $3 $4 } 转换成 {if ( $0 !~ /matchme/ ) {print $1 $3 $4}} 这两个脚本都只输出不包含 matchme 字符序列的那些行。此外还可以选择最适合您的代码的方法。它们的功能完全相同。 awk 还允许使用布尔运算符 “||”逻辑与和 “”逻辑或以便创建更复杂的布尔表达式 ( $1 “foo” ) ( $2 “bar” ) { print } 这个示例只打印第一个字段等于 foo 且第二个字段等于 bar 的那些行。 数值变量至今我们不是打印字符串、整行就是特定字段。然而awk 还允许我们执行整数和浮点运算。通过使用数学表达式可以很方便地编写计算文件中空白行数量的脚本。以下就是这样一个脚本 BEGIN { x0 }/^$/ { xx1 }END { print “I found ” x ” blank lines. :)” } 在 BEGIN 块中将整数变量 x 初始化成零。然后awk 每次遇到空白行时awk 将执行 xx1 语句递增 x。处理完所有行之后执行 END 块awk 将打印出最终摘要指出它找到的空白行数量。 字符串化变量awk 的优点之一就是“简单和字符串化”。我认为 awk 变量“字符串化”是因为所有 awk 变量在内部都是按字符串形式存储的。同时awk 变量是“简单的”因为可以对它执行数学操作且只要变量包含有效数字字符串awk 会自动处理字符串到数字的转换步骤。要理解我的观点请研究以下这个示例 x”1.01″# We just set x to contain the *string* “1.01″xx1# We just added one to a *string*print x# Incidentally, these are comments awk 将输出 2.01 有趣吧虽然将字符串值 1.01 赋值给变量 x我们仍然可以对它加一。但在 bash 和 python 中却不能这样做。首先bash 不支持浮点运算。而且如果 bash 有“字符串化”变量它们并不“简单”要执行任何数学操作bash 要求我们将数字放到丑陋的 $( ) ) 结构中。如果使用 python则必须在对 1.01 字符串执行任何数学运算之前将它转换成浮点值。虽然这并不困难但它仍是附加的步骤。如果使用 awk它是全自动的而那会使我们的代码又好又整洁。如果想要对每个输入行的第一个字段乘方并加一可以使用以下脚本 { print ($1^2)1 } 如果做一个小实验就可以发现如果某个特定变量不包含有效数字awk 在对数学表达式求值时会将该变量当作数字零处理。 众多运算符awk 的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除awk 还允许使用前面演示过的指数运算符 “^”、模余数运算符 “%” 和其它许多从 C 语言中借入的易于使用的赋值操作符。 这些运算符包括前后加减i、–foo、加减乘除赋值运算符 a3、b*2、c/2.2、d-6.2。不仅如此 — 我们还有易于使用的模指数赋值运算符a^2、b%4。 字段分隔符awk 有它自己的特殊变量集合。其中一些允许调整 awk 的运行方式而其它变量可以被读取以收集关于输入的有用信息。我们已经接触过这些特殊变量中的一个FS。前面已经提到过这个变量让您可以设置 awk 要查找的字段之间的字符序列。我们使用 /etc/passwd 作为输入时将 FS 设置成 “:”。当这样做有问题时我们还可以更灵活地使用 FS。 FS 值并没有被限制为单一字符可以通过指定任意长度的字符模式将它设置成规则表达式。如果正在处理由一个或多个 tab 分隔的字段您可能希望按以下方式设置 FS FS”/t” 以上示例中我们使用特殊 “” 规则表达式字符它表示“一个或多个前一字符”。 如果字段由空格分隔一个或多个空格或 tab您可能想要将 FS 设置成以下规则表达式 FS”[[:space:]]” 这个赋值表达式也有问题它并非必要。为什么因为缺省情况下FS 设置成单一空格字符awk 将这解释成表示“一个或多个空格或 tab”。在这个特殊示例中缺省 FS 设置恰恰是您最想要的 复杂的规则表达式也不成问题。即使您的记录由单词 “foo” 分隔后面跟着三个数字以下规则表达式仍允许对数据进行正确的分析 FS”foo[0-9][0-9][0-9]” 字段数量接着我们要讨论的两个变量通常并不是需要赋值的而是用来读取以获取关于输入的有用信息。第一个是 NF 变量也叫做“字段数量”变量。awk 会自动将该变量设置成当前记录中的字段数量。可以使用 NF 变量来只显示某些输入行 NF 3 { print “this particular record has three fields: ” $0 } 当然也可以在条件语句中使用 NF 变量如下 {if ( NF 2 ) {print $1 ” ” $2 “:” $3}} 记录号记录号 (NR) 是另一个方便的变量。它始终包含当前记录的编号awk 将第一个记录算作记录号 1。迄今为止我们已经处理了每一行包含一个记录的输入文件。对于这些情况NR 还会告诉您当前行号。然而当我们在本系列以后部分中开始处理多行记录时就不会再有这种情况所以要注意可以象使用 NF 变量一样使用 NR 来只打印某些输入行 (NR 10 ) || (NR 100) { print “We are on record number 1-9 or 101” } 另一个示例 {#skip headerif ( NR 10 ) {print “ok, now for the real information!”}} awk 提供了适合各种用途的附加变量。我们将在以后的文章中讨论这些变量。 现在已经到了初次探索 awk 的尾声。随着本系列的开展我将演示更高级的 awk 功能我们将用一个真实的 awk 应用程序作为本系列的结尾。同时如果急于学习更多知识请参考以下列出的参考资料。