Awk搜索表达式和OFS

时间:2013-06-24 12:56:09

标签: search awk

我正在尝试打印sar输出,不包括带有主机名和日期的标头。以下命令也不能排除标题行和输出字段分隔符:

sar -u|head -5|awk -F '
  BEGIN { hname="'"`hostname -s`"'"; hdt="'"`date +"%d-%b-%Y" `"'" ; OFS="," ;}
  { $1 ~ /[0-9]/ && $4 ~ /[0-9]/ }
  { printf( "h=%-15s d=%11s 1=%8s 2=%2s 3=%-3s 4=%6.2f 5=%6.2f 6=%6.2f 7=%6.2f 8=%6.2f 9=%6.2f\n", hname, hdt, $1, $2, $3, $4, $5, $6, $7, $8, $9 );}'

但是当使用相同的搜索时,它运行良好!

2 个答案:

答案 0 :(得分:1)

请尝试以下代码:

sar -u|head -5|awk '
  BEGIN { hname="'"`hostname -s`"'"; hdt="'"`date +"%d-%b-%Y" `"'" ; OFS="," ;} 
  $1 ~ /[0-9]/ && $4 ~ /[0-9]/
  { printf( "h=%-15s d=%11s 1=%8s 2=%2s 3=%-3s 4=%6.2f 5=%6.2f 6=%6.2f 7=%6.2f 8=%6.2f 9=%6.2f\n", hname, hdt, $1, $2, $3, $4, $5, $6, $7, $8, $9 );}'

请注意,这是未经测试的,因为我没有安装sar程序。 如果您粘贴该程序的一些示例输出,我可以测试代码并相应地更新我的答案。

这是尽可能最接近您的代码,如果我没有错过任何其他内容,应该可以使用。 您使用的-F选项未执行任何操作,因为您未指定新的字段分隔符FS)。 请注意,我删除了“search ”语句{...}周围的大括号(大括号$1 ~ /[0-9]/ && $4 ~ /[0-9]/)。

awk程序由模式和关联的操作组成,这些模式是为那些记录执行的(没有其他选项,每个line被视为与模式匹配的记录操作必须在相应的模式之后用大括号括起来。

所以你的代码有三个动作:初始化与特殊的 BEGIN模式相关联,因此在读取任何输入之前执行一次两个为所有记录(即行)执行的操作,因为它们与任何模式无关:第一个评估搜索表达式,第二个打印格式化的记录。但请注意,这两个操作 已关联,无论您的搜索表达式是评估为true还是false,都会执行打印操作。

要了解您的代码有什么问题,您可以运行此详细版本:

sar -u|head -5|awk '
  BEGIN { hname="'"`hostname -s`"'"; hdt="'"`date +"%d-%b-%Y" `"'" ; OFS="," ;} 
  {print "search returned "($1 ~ /[0-9]/ && $4 ~ /[0-9]/?"true.":"false.")}
  { printf( "h=%-15s d=%11s 1=%8s 2=%2s 3=%-3s 4=%6.2f 5=%6.2f 6=%6.2f 7=%6.2f 8=%6.2f 9=%6.2f\n", hname, hdt, $1, $2, $3, $4, $5, $6, $7, $8, $9 );}'

这会扩展您的第一个操作以打印搜索表达式的结果,您将看到第二个(即printf操作是独立执行的结果。

通过删除搜索表达式周围的大括号,可以使模式与下一个操作printf相关联。这样,printf仅针对与您的搜索模式匹配的记录(即行)执行。

进一步注意,如果通过as suggested将外部命令的输出存储在变量@jaypal singh中,则代码会更易读,下面通过使用{{1}初始化awk变量来实现选项:

-v

<强>附录:

<{3}} As pointed out输出字段分隔符sar -u|head -5|awk \ -v hname="`hostname -s`" \ -v hdt="`date +"%d-%b-%Y"`" \ -v OFS="," \ ' $1 ~ /[0-9]/ && $4 ~ /[0-9]/{ printf( "h=%-15s d=%11s 1=%8s 2=%2s 3=%-3s 4=%6.2f 5=%6.2f 6=%6.2f 7=%6.2f 8=%6.2f 9=%6.2f\n", hname, hdt, $1, $2, $3, $4, $5, $6, $7, $8, $9 ) } ' )不会影响OFS,因此您可能希望使用逗号({ {1}})而不是prinft语句中的空格(,),而不是定义

printf

请注意,这次我还从管道中删除了OFS,因为您在评论中声明这是出于测试原因而引入的,如果它没有使用记录号({ {1}}} @jaypal singh as suggested会更好{。{3}}。

答案 1 :(得分:0)

以下是您需要做的事情:

$ hname=$(hostname -s)
$ hdt=$(date +"%d-%b-%Y")
$ $ sar -u | awk '$1~/[0-9]/&&$4~/[0-9]/&&NR<=5{print host,dat,$1,$2,$3,$4,$5,$6,$7,$8,$9}' OFS="," host="$hname" dat="$hdt"

一些指示:

  • 不需要head,您可以使用NR变量控制行数
  • 要在awk中使用bash命令,您需要使用system(),或者您可以将bash命令存储在变量中,并像我们上面所做的那样在awk中调用它们。
  • 输出分隔符变量 OFSORSprintf语句没有影响