2012-07-10 122 views
2

我想编写一个高效的awk脚本,它将采用类似于下面所示摘录的文件并打印某一行(例如,以“Time(UTC)”开头的行) :“)从每个匹配的记录。我相信这比我过去做的更好。awk从匹配段落高效地打印匹配行

示例文件(对不起,我不知道如何把空行的代码框中他们通过“空行”表示。):

Processor: Some_Proc 
Capsule abortion no 32 
Time (UTC): Fri Jun 15 06:25:10 2012 
CapsuleId: 1704167 
CapsuleName: SomeAppProc 
Reason: Assertion "Reason1" 
BLANK LINE 
Processor: Some_Proc 
Capsule abortion no 33 
Time (UTC): Fri Jun 15 06:25:10 2012 
CapsuleId: 1704168 
CapsuleName: SomeAppProc 
Reason: Assertion "Reason2" 
BLANK LINE 
Processor: Some_Proc 
Capsule abortion no 34 
Time (UTC): Fri Jun 15 06:25:10 2012 
CapsuleId: 1704168 
CapsuleName: SomeAppProc 
Reason: Assertion "Reason1" 

前面的代码示例(对不起,我不知道如何在这个论坛上,我试过8位保留相同的缩进,但没有工作)

BEGIN { 
    RS="" #Each record is a "paragraph" 
    FS="\n" #Each field is a line 
} 

/Reason1/ { 
    # print $3 would work if it always shows up on the third line 
    # but the following for loop should find it if it's on a different line 
    for (i=1;i<=NF;i++) { 
     if ($i ~ /^Time.*/) { 
      print $i 
      next 
     } 
    } 
} 

是否有打印行,如果它并不总是以相同的顺序进行更有效的方式?

谢谢

回答

1

如何这样的事情?:

BEGIN { reset(); } 
END { reset(); } 
$0 == "" { reset(); } 
/^Reason:/ && $3 == "\"Reason1\"" { found = 1; } 
/^Time \(UTC\):/ { time = $0; } 

function reset() { 
    if (found) { print time; } 
    found = 0; 
    time = "(unknown)"; 
} 

,然后只用换行默认的记录分隔符。这些功能会在读取时记录时间和原因字段,然后在每个匹配记录的末尾打印出时间。

1

这对我来说似乎是一个很好的解决方案。我会用同样的方法来解决这个问题。我会使用break而不是next,因为您希望在找到该行后停止循环。 next指令没什么意义,因为它执行循环的下一个循环,如果它不在那里,它也是一样的。

for (i=1;i<=NF;i++) { 
    if ($i ~ /^Time.*/) { 
     print $i 
     break 
    } 
} 
+0

我还没有尝试过这段代码,但我试图使用将停止处理当前记录并继续到下一条记录的命令。 – 2012-07-10 18:54:11