【问题标题】:A question about AWK multiple line recognition关于AWK多行识别的一个问题
【发布时间】:2019-09-17 03:31:52
【问题描述】:

我刚刚阅读了Can awk patterns match multiple lines?,其接受的解决方案是打印first half 之后的行的脚本。

how
second half #1
now
first half
second half #2
brown
second half #3
cow
/second half/ {
  if(lastLine == "first half") {
    print
  }
}

{ lastLine = $0 }

这给出了second half #2

无法理解为什么{ lastLine = $0 } 必须追随 /second half/ {...}/。我尝试交换它们,但我什么都没有

{ lastLine = $0 }

/second half/ {
  if(lastLine == "first half") {
    print
  }
}

我尝试阅读 man awk,但它涵盖状态机。搜索“awk 状态机”只会给出链接的 SO 问题。

【问题讨论】:

  • if 语句引用变量​​lastLine,所以很明显lastLine 是在if 之前还是之后获取它的值(除非我根本不理解你的问题)。
  • 在第二个脚本中,lastLine 获得了if 之前的值,但我不明白为什么没有打印出来。
  • 在第二个脚本中,lastLine 设置为当前行(即$0),只有当当前行匹配second half 时才会执行其后的动作。在操作中,检查lastLine 变量是否为first half,结果始终为false,因为second half ... =/= first half。因此没有任何内容被打印出来。
  • 看,在第一个脚本lastLine 保留最后一行,但第二个保留当前行,好吗?因为在第一个,它被分配之后检查它是否是first half,在第二个,它被分配之前检查它是否是first half
  • 如何写一个状态机是一般编程的事情,不是awk的事情。见en.wikipedia.org/wiki/Finite-state_machine(如果你关心的话,还有一个非常年轻的男人和他的同龄人在ieeexplore.ieee.org/document/6772875发表的一篇非常古老的论文:-))

标签: awk


【解决方案1】:

@oguzismail 的评论回答了这个问题。为了从未回答的队列中清除这个问题,我将把它扩展为一个答案。

AWK 处理文本记录方式。默认情况下,记录分隔符 (RS) 是换行符 \n,因此 AWK 将每一行视为一条记录。

在第一个(正确的)AWK 脚本中,当处理第一条记录how 时,匹配/second half/ in

/second half/ {
  if(lastLine == "first half") {
    print
  }
}

被评估为 false 并且{ lastLine = $0 } 将当前记录$0(即how)保存到变量lastLine

然后第二条记录second half #1来了,它匹配/second half/,所以块{if (lastLine == "first half"){...}}lastLine作为前一条记录(how)执行,即使$0second half #1 .

随着过程的进行,记录 second half #2 最终会通过嵌套块 {} 从而被打印出来。

如果我在 AWK 脚本中反转这两个操作,lastLine 将始终保存当前记录 $0,而当且仅当 $0 包含 second half 时,/second half/ 才会匹配,确实如此't 等于 first half。因此,第二个nd AWK 脚本不可能$0 得到printed。

【讨论】:

    猜你喜欢
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多