1

我正在为我的 flex 扫描器整理最后一个模式,用于解析 AWK 源代码。

我无法弄清楚如何匹配 AWK 源代码中使用的正则表达式,如下所示:

{if ($0 ~ /^\/\// ){ #Match for "//" (Comment)

或更简单地说:

else if ($0 ~ /^Department/){

其中 AWK 正则表达式封装在“/ /”中。

到目前为止,我尝试过的所有 Flex 模式都与我的整个输入文件匹配。我尝试更改正则表达式模式的优先级,但没有找到运气。帮助将不胜感激!

4

2 回答 2

2

正则表达式 regexen 必须是某个地方的模因。无论如何,让我们试一试。

一个 gawk 正则表达式包括:

  • /

  • 任意数量的正则表达式组件

  • /

正则表达式组件(简化形式——注 1)是以下之一:

  • 以外的任何字符/[\

  • a\后跟任何单个字符(不过,我们现在不会进入换行符。

  • 一个字符类(见下文)

到这里很容易。现在是有趣的部分。

一个字符类是:

  • [[^[][^] (注 2)

  • 任意数量的字符类组件

  • ]

字符类组件是(理论上,但请参阅下面的 gawk 错误)以下之一:

  • ]或以外的任何单个字符\(注 3)

  • a\后跟任何单个字符

  • 一个字符类

  • 排序规则类

一个字符类是:(注5)

  • [:

  • 一个有效的类名,它总是一个字母字符序列,但不做假设可能更安全。

  • :]

排序规则类大多未实现但部分解析。您可能会忽略它们,因为 gawk 似乎还没有正确处理它们(注 4)。但对于它的价值:

  • [.

  • 一些多字符整理字符,例如荷兰语语言环境中的“ij”(我认为)。

  • .]

或等价类:

  • [=

  • 一些字符,或者也可能是一个多字符排序规则字符

  • =]

重要的一点是不会[/]终止正则表达式。你不需要写。(你不需要做任何事情来实现它。我只是提到它。)。[\/]


注1:

实际上,\字符类和字符类的解释要复杂得多。我只是描述了足够的词法分析。如果你真的想将正则表达式解析成它们的点点滴滴,那就更烦人了。

例如,您可以使用\dddor \xHH(例如\203or \x4F)指定任意八位字节。然而,我们不需要关心,因为转义序列中没有什么是特殊的,所以对于词法分析而言,这并不重要;我们将得到词素的正确结尾。同样,我没有费心描述字符范围和-字符类内部的特殊规则,我也不担心正则表达式元字符(){}?*+.,因为它们不进入词法分析。您确实必须担心,[]因为它可以隐式隐藏 a 以/防止终止正则表达式。(我曾经写过一个正则表达式解析器,它可以让你隐藏/在带括号的表达式中,我认为这很酷——它减少了很多 kilroy-was-here 噪音(\/)——但似乎没有其他人认为这是个好主意。)


笔记2:

尽管 gawk\在字符类中做错了(见下面的注 3),但它并不要求你使用它们,所以你仍然可以使用 Posix 行为。Posix 行为是]如果它是字符类中的第一个字符,则不会终止字符类,可能在否定^. 处理这个问题的最简单方法是让字符类以四个可能的序列中的任何一个开始,总结如下:

\[^?]?


注3:

gawk 与 Posix ERE(扩展正则表达式)的不同之处在于它将\字符类内部解释为转义字符。Posix 要求\在字符类中失去其特殊含义。我觉得 gawk 这样做很烦人(许多其他正则表达式库也是如此,同样烦人。)特别烦人的是 gawk 信息手册说 Posix 要求它这样做,而实际上它需要相反。但这只是我。无论如何,傻眼:

/[\]/]/

是匹配]或匹配的正则表达式/。在 Posix 中,去掉封闭/的 s ,这将是一个正则表达式,它匹配 a\后跟 a/后跟 a ]。(gawk 和 Posix 都要求]它在不被视为字符类终止符时不是特殊的。)


注4:

我的机器上安装的 gawk 版本中有一个错误,正则表达式解析器在整理类结束时会混淆。所以它认为正则表达式在第一秒终止/

/[[.a.]/]/

虽然它是正确的:

/[[:alpha:]/]/

当然,把斜线放在第一位总是有效的:

/[/[:alpha:]]/


注5:

字符类和整理类和朋友的解析有点棘手,因为它们有两个字符的终止符。“写一个正则表达式来识别 C /* */ 评论”曾经是一个标准的面试问题,但我想它不再是了。无论如何,这是一个解决方案(对于 [:...:],但如果您愿意,只需将 : 替换为其他标点符号):

[[]:([^:]|:*[^]:])*:+[]]   // Yes, I know it's unreadable. Stare at it a while.
于 2012-09-25T04:40:14.187 回答
0

正则表达式可以在没有“/.../”的情况下工作,请参见示例:

print all numbers starting with 7 from 1-100:

kent$  seq 100|awk '{if($0~"7[0-9]")print}'
70
71
72
73
74
75
76
77
78
79

kent$  awk --version
GNU Awk 3.1.6
于 2012-09-25T09:07:52.283 回答