所以,我正在为一所学校的项目工作,我们必须做一个壳,直到现在我一直很好。我需要弄清楚如何扩展我的正则表达式" words"以便识别特殊字符。
基本上,我需要能够通过某些特殊字符来分隔单词,但如果它们被转义则不能。
例如: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
之类的内容,但我不确定如何扩展它以查找除空格或特殊字符之外的任何字符,除非该特殊字符被转义。
感谢任何帮助。
答案 0 :(得分:2)
怎么样:
(?:\\.|[^ \t\n<>&|])*
这&#34;打破了字#34;在,
\t
,\n
,<
,>
,&
和|
上(即{{1} }}),除非转义。
演示:https://regex101.com/r/lEkNRk/1
[^ \t\n<>&|]
这也单独匹配(?:\\.|[^ \t\n<>&|])+|[ \t\n<>&|]
,等等,如果没有转义。也许它更适合您建议的
>
模式。
答案 1 :(得分:1)
如果你正在使用(f)lex,你可能会想要这样的东西。它基于Posix 2016中的语法摘要,为了好玩而引入了几个基本原理,我尝试使用与该文档相同的令牌名称。
这里省略了许多重要的功能:
正确处理报价需要做更多工作。我甚至都没试过。 (最令人讨厌的部分是,您可以在引用的字符串中包含命令扩展$(...)
,这是一个独立的词汇上下文。)
我没有包含将yytext
的副本保存到yylval
的代码,这需要针对WORD
以及保留字进行(但是不是元字符或以元字符开头的符号)因为保留字并不总是保留。这个事实也会在语法中产生一些问题。
我没有区分NAME
和WORD
(规则5和8)。
我没有费心去识别IO_NUMBER
,尽管使用(f)lex的尾随上下文运算符非常简单。 (如果紧随该号码后面的字符为<
或>
,则号码才有用。
我也没有尝试识别ASSIGNMENT_WORD
(见2.10.1)。赋值在语法上并不重要,但它们在语义上很重要,在识别这些单词时设置标志很有用。可以在ASSIGNMENT_WORD
模式之前添加用于识别yylval
并在WORD
中设置标记的模式(请参阅下面有关排序模式的说明)。
下面列出了这些模式的顺序。当多个模式匹配相同的标记时,(f)lex具有定义的匹配顺序这一事实通常大大简化了正则表达式的构造,但这也意味着在某些情况下必须仔细地对规则进行排序。
[|&;()<>\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
规则之前,以便在它们形成完整的单词时正确识别它们。
类似地,#
字符仅在单词中的第一个字符时才开始注释。否则,它是一个普通的单词字符。同样,识别(并忽略)注释需要匹配规则在WORD
之前。请注意,规则不匹配终止评论的换行符;与任何其他换行符一样,换行符实际上具有语法重要性,因此必须将其返回给解析器。