如何匹配行开始?
How to match the line begin?
我正在用 lex 编写 cat(1)
实用程序。
当我考虑如何实现选项 -n
时,即为每一行编号。
但我必须这样写:
^. {
printf("%8d ", ++lino);
ECHO;
}
我知道行尾(EOL)可以匹配使用锚点$
和\n
,所以我想知道是否有类似的东西可以匹配行首(BOL)锚点,所以我不必使用 ECHO;
(我同意 Joachim Pileborg 的评论,即 lex
是 而不是 实现 cat
的工具。这个答案的其余部分本着解释一下 lex
的精神。)
如果输入中有空行,所提供的 lex 程序将无法运行,因为 ^.
不匹配空行。 (在 lex 中,.
不匹配换行符。)因此,合理最小的 (f)lex 输入文件将是:
%options noyywrap noinput nounput
%%
int lino = 0;
^(.|\n) { printf("%8d %c", ++lino, *yytext); }
这里我只是打印出printf
中匹配的token,相当于使用ECHO
。所以它并不是真的 "eliminate" ECHO
.
(f)lex 规则必须至少匹配一个字符。因此,一个模式不可能仅由 $
组成,就像一个模式仅由 ^
(这是一个 BOL 锚点)组成一样。从这个意义上说,您问题的答案很简单 "no".
一个更容易理解(并且可能更有效)的解决方案是实际匹配每一行。这个解决方案 never 使用 ECHO
,甚至在默认规则中也不使用,所以我告诉 flex 不要生成默认规则:
%options noyywrap noinput nounput nodefault
%%
int lino = 0;
.*\n? { printf("%8d %s", ++lino, yytext); }
这不是很完美,因为它会截断包含 NUL 字符的行。 (也就是说,printf
将有效地截断该行;该行将被正确解析。)要修复它,有必要使用 fwrite
而不是 printf
:
%options noyywrap noinput nounput nodefault
%%
int lino = 0;
.*\n? { printf("%8d %s", ++lino);
fwrite(yytext, 1, yyleng, yyout); }
换行符是可选的 (\n?
),以防文件的最后一行没有以换行符结尾。因为 (f)lex 模式从不匹配零个字符,所以该规则实际上等同于更精确但更笨重的正则表达式 .*\n|.+
.
我正在用 lex 编写 cat(1)
实用程序。
当我考虑如何实现选项 -n
时,即为每一行编号。
但我必须这样写:
^. {
printf("%8d ", ++lino);
ECHO;
}
我知道行尾(EOL)可以匹配使用锚点$
和\n
,所以我想知道是否有类似的东西可以匹配行首(BOL)锚点,所以我不必使用 ECHO;
(我同意 Joachim Pileborg 的评论,即 lex
是 而不是 实现 cat
的工具。这个答案的其余部分本着解释一下 lex
的精神。)
如果输入中有空行,所提供的 lex 程序将无法运行,因为
^.
不匹配空行。 (在 lex 中,.
不匹配换行符。)因此,合理最小的 (f)lex 输入文件将是:%options noyywrap noinput nounput %% int lino = 0; ^(.|\n) { printf("%8d %c", ++lino, *yytext); }
这里我只是打印出
printf
中匹配的token,相当于使用ECHO
。所以它并不是真的 "eliminate"ECHO
.(f)lex 规则必须至少匹配一个字符。因此,一个模式不可能仅由
$
组成,就像一个模式仅由^
(这是一个 BOL 锚点)组成一样。从这个意义上说,您问题的答案很简单 "no".一个更容易理解(并且可能更有效)的解决方案是实际匹配每一行。这个解决方案 never 使用
ECHO
,甚至在默认规则中也不使用,所以我告诉 flex 不要生成默认规则:%options noyywrap noinput nounput nodefault %% int lino = 0; .*\n? { printf("%8d %s", ++lino, yytext); }
这不是很完美,因为它会截断包含 NUL 字符的行。 (也就是说,
printf
将有效地截断该行;该行将被正确解析。)要修复它,有必要使用fwrite
而不是printf
:%options noyywrap noinput nounput nodefault %% int lino = 0; .*\n? { printf("%8d %s", ++lino); fwrite(yytext, 1, yyleng, yyout); }
换行符是可选的 (
\n?
),以防文件的最后一行没有以换行符结尾。因为 (f)lex 模式从不匹配零个字符,所以该规则实际上等同于更精确但更笨重的正则表达式.*\n|.+
.