我正在用lex编写cat(1)
实用程序。
当我考虑如何实现选项-n
时,即每行编号。
但我必须写这样的东西:
^. {
printf("%8d ", ++lino);
ECHO;
}
我知道行尾(EOL)可以匹配使用锚$
和\n
,所以我想知道是否有相似的东西来匹配行首(BOL)锚点,所以我不必使用ECHO;
答案 0 :(得分:2)
(我同意Joachim Pileborg的评论lex
cat
的工具。其余的答案是本着解释一下lex
。)
如果输入中有空行,则提供的lex程序将无效,因为^.
与空行不匹配。 (在lex中,.
与换行符不匹配。)因此,一个合理的最小(f)lex输入文件将是:
%options noyywrap noinput nounput
%%
int lino = 0;
^(.|\n) { printf("%8d %c", ++lino, *yytext); }
在这里,我只打印printf
中匹配的令牌,这相当于使用ECHO
。所以它并没有真正“消除”ECHO
。
(f)lex规则必须至少匹配一个字符。因此,模式实际上不可能只由$
组成,而模式只能由^
(这是一个BOL锚点)组成。从这个意义上讲,你的问题的答案就是“不”。
更容易理解(可能更有效)的解决方案是实际匹配每一行。此解决方案从不使用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|.+
。