2

我想编写一个高效的 awk 脚本,该脚本将采用类似于下面显示的摘录的文件并从每个匹配的记录中打印某一行(例如,以“时间(UTC):”开头的行)。我相信有比我过去所做的更好的方法来做到这一点。

示例文件(对不起,我不知道如何在代码框中放置空行。它们由“BLANK LINE”表示):

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
        }
    }
} 

如果它并不总是以相同的顺序出现,是否有更有效的方法来打印该行?

谢谢

4

2 回答 2

1

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

for (i=1;i<=NF;i++) {
    if ($i ~ /^Time.*/) {
        print $i
        break
    }
}
于 2012-07-10T17:38:12.080 回答
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)";
}

然后只需使用换行符的默认记录分隔符。这样做是在读取时间和原因字段时记下它们,然后在每个匹配记录的末尾打印出时间。

于 2012-07-10T22:51:29.150 回答