所以,我正在为学校做一个项目,我们必须做一个shell,直到现在我一直很好。我需要弄清楚如何扩展我的正则表达式“单词”,以便识别特殊字符。
基本上,我需要能够通过某些特殊字符来分隔单词,但如果它们被转义则不能。
例如:echo sometext>file.txt
将被标记为WORD WORD GREAT WORD
。但是,echo sometext\>file.txt
将被标记为WORD WORD
,其中“sometext> file.txt”都是一个单词。
我无法找出可以处理这个问题的正则表达式。这就是我目前所拥有的:[^ \t\n][^ \t\n<>&|]*
。这适用于挑选像echo sometext>file.txt
这样的东西,但我不知道如何扩展它以寻找除空格或特殊字符之外的任何字符,除非转义特殊字符。
任何帮助表示赞赏。
怎么样:
(?:\\.|[^ \t\n<>&|])*
这在,
\t
,\n
,<
,>
,&
和|
(即[^ \t\n<>&|]
)中“打破了”,除非逃脱。
但是:ぁzxswい
https://regex101.com/r/lEkNRk/1
如果没有逃脱,这也单独匹配(?:\\.|[^ \t\n<>&|])+|[ \t\n<>&|]
,等。也许它更适合您建议的
>
模式。
但是:ぁzxswい
如果你使用(f)lex,你可能会想要这样的东西。它基于WORD WORD GREAT WORD
中的语法摘要,为了好玩而引入了几个bashisms,我尝试使用与该文档相同的令牌名称。
这里省略了许多重要功能:
$(...)
的代码,这需要为yytext
以及保留字(但不是元字符或以元字符开头的符号)完成,因为保留字并不总是保留。这个事实也会在语法中产生一些问题。yylval
和WORD
(规则5和8)。NAME
,尽管使用(f)lex的尾随上下文运算符非常简单。 (如果紧跟在数字后面的字符是WORD
或IO_NUMBER
,则数字才是特殊的。<
(见2.10.1)。赋值在语法上并不重要,但它们在语义上很重要,在识别这些单词时设置标志很有用。可以在>
模式之前添加识别ASSIGNMENT_WORD
s并在ASSIGNMENT_WORD
中设置标记的模式(请参阅下面有关排序模式的说明)。下面列出了这些模式的顺序。当多个模式匹配相同的标记时,(f)lex具有定义的匹配顺序这一事实通常大大简化了正则表达式的构造,但这也意味着在某些情况下必须仔细排序规则。
yylval
这些模式集合经过精心设计,以便生成正确的令牌;模式不是相互排斥的。特别是:
WORD
规则不允许它们。另一方面,[|&;()<>\n] return *yytext; /* Metacharacters, including newline */
[[:space:]] ; /* Ignore other whitespace */
"||" return OR_IF; /* Multi-metacharacter sequences */
"&&" return AND_IF;
";;" return DSEMI;
"<<" return DLESS;
"<<-" return DLESSDASH;
"<<<" return TLESS; /* Bash here strings */
">>" return DGREAT;
"<&" return LESSAND;
">&" return GREATAND;
"<>" return LESSGREAT;
">|" return CLOBBER;
"((" return DLparen; /* Bash arithmetic conditional */
"))" return DRparen;
"if" return If; /* reserved words, only matched when */
"then" return Then; /* they are a complete word (and often */
"else" return Else; /* treated as regular words even then).*/
"elif" return Elif;
"fi" return Fi;
"do" return Do;
"done" return Done;
"case" return Case;
"esac" return Esac;
"while" return While;
"until" return Until;
"for" return For;
"in" return In;
"time" return Time; /* In bash, this is reserved */
"{" return Rbrace;
"}" return Lbrace;
"!" return Bang;
"[[" return DLbracket; /* Bash conditional */
"]]" return DRbracket;
"#".* ; /* Comments. Only if # would start a word. */
([^[:space:]|&;()<>]|\\.)+ return WORD;
,WORD
和{
不是元字符,尽管它们在某些情况下具有语法意义;首先必须将它们识别为单词以便使用。在这个意义上,它们类似于}
和!
等关键词;他们的模式需要在if
规则之前出现,以便在它们形成完整的单词时正确识别它们。for
字符仅在单词中的第一个字符时才开始注释。否则,它是一个普通的单词字符。同样,识别(并忽略)注释需要匹配规则在WORD
之前。请注意,该规则与终止注释的换行符不匹配;与任何其他换行符一样,换行符实际上具有语法重要性,因此必须将其返回给解析器。