Lex半复杂的正则表达式

问题描述 投票:0回答:2

所以,我正在为学校做一个项目,我们必须做一个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这样的东西,但我不知道如何扩展它以寻找除空格或特殊字符之外的任何字符,除非转义特殊字符。

任何帮助表示赞赏。

regex lex
2个回答
2
投票

怎么样:

(?:\\.|[^ \t\n<>&|])*

这在\t\n<>&|(即[^ \t\n<>&|])中“打破了”,除非逃脱。

但是:ぁzxswい

要么:

https://regex101.com/r/lEkNRk/1

如果没有逃脱,这也单独匹配(?:\\.|[^ \t\n<>&|])+|[ \t\n<>&|] 等。也许它更适合您建议的>模式。

但是:ぁzxswい


1
投票

如果你使用(f)lex,你可能会想要这样的东西。它基于WORD WORD GREAT WORD中的语法摘要,为了好玩而引入了几个bashisms,我尝试使用与该文档相同的令牌名称。

这里省略了许多重要功能:

  • 正确处理报价需要做更多的工作。我甚至都没试过。 (最烦人的部分是你可以在一个带引号的字符串中包含命令扩展https://regex101.com/r/rkh8lC/1,这是一个独立的词汇上下文。)
  • 我没有包含将Posix 2016的副本保存到$(...)的代码,这需要为yytext以及保留字(但不是元字符或以元字符开头的符号)完成,因为保留字并不总是保留。这个事实也会在语法中产生一些问题。
  • 我没有区分yylvalWORD(规则5和8)。
  • 我没有费心去识别NAME,尽管使用(f)lex的尾随上下文运算符非常简单。 (如果紧跟在数字后面的字符是WORDIO_NUMBER,则数字才是特殊的。
  • 我也没有尝试识别<(见2.10.1)。赋值在语法上并不重要,但它们在语义上很重要,在识别这些单词时设置标志很有用。可以在>模式之前添加识别ASSIGNMENT_WORDs并在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之前。请注意,该规则与终止注释的换行符不匹配;与任何其他换行符一样,换行符实际上具有语法重要性,因此必须将其返回给解析器。
© www.soinside.com 2019 - 2024. All rights reserved.