如何为包含所有元音至少一次的字符串生成正则表达式?

时间:2015-11-03 15:16:41

标签: regex flex-lexer

您可能认为这是this的重复问题。

实际上这是一个类似的问题。那我为什么要再问一次呢?

因为,该问题的接受答案不起作用。答案可能符合OP的要求,但这不是一般答案。

另一个原因是,它应该在flex中工作。

我需要一个正则表达式,它只接受那些包含任意顺序元音的字符串。

它可能有其他一些字母,但所有元音必须至少出现一次。

让我们看一些例子:

String                         Accepted or Not
----------------------         ---------------
abceioussa                     Accepted
aeiou                          Accepted
uioae                          Accepted
odsidsfusjldkfuuuu             Not Accepted
bcesdddsoaiaaau                Accepted
aaaaaaaaeeeeeeeooooiu          Accepted
aasssssaeeeeeeeoeoooi          Not Accepted

编辑:

请记住,它应该适用于flex

编辑2:

任务:

Pattern                                                         Action
-------------------------------------------------------------   --------------------
Blank Space, tab space                                          Do nothing
New line                                                        Count number of line
Any word contains all five vowels at least once                 Print VOWELS
Any word ends with s or es                                      Print PLURAL
Any word ends with ly                                           Print ADVERB
Any word ends with ing                                          Print CONTINUOUS
is/do/go/be/are/was/were/did                                    Print VERB
a/an/the                                                        Print ARTICLE
Any word starts with uppercase letter and none of the above     Print NOUN
Anything else                                                   Print NOT_RECOGNIZED

Scanner4.l:

看一下只需填写常规定义vowel的表达式。

%{
    /* comments */
    #define ECHO fwrite(yytext, yyleng,1,yyout);
    int yylineno = 0, ii;
%}
letter [a-zA-Z]
uppercase [A-Z]
digit [0-9]
digits [0-9]+
punc [-=\+\\_\.,\.\|\~\!\$\%\^\&\(\\;\'\"\?\{\}\[\]\)\/\#\*@]
anything ({letter}|{digit})
spacetab [\t ]+
endmark [\n\t ]
dot [\.]
hp [\-]
verb (is|do|go|be|are|was|were|did)
article (a|an|the)
normal ({anything}|{punc})
vowel //here you have to write the expression
%option noyywrap
%%
{spacetab}|{punc}   { 
                        fprintf(yyout,"%s", yytext);
                        printf(":%s:%d ECHO\n",yytext,yylineno);
                        /* do nothing */
                    }
\n  {
        yylineno++; 
        ECHO; 
        printf(":%s:%d no echo\n",yytext,yylineno);
    }
{vowel}{endmark}    {
                        fprintf(yyout," VOWELS ");
                        fprintf(yyout,"%c", yytext[yyleng-1]);
                        if(yytext[yyleng-1]=='\n') yylineno++;
                        printf(":%s:%d vowels\n",yytext,yylineno);
                    }
{verb}{endmark}     {
                        fprintf(yyout," VERB ");
                        fprintf(yyout,"%c", yytext[yyleng-1]);
                        if(yytext[yyleng-1]=='\n') yylineno++;
                        printf(":%s:%d verb\n",yytext,yylineno);
                    }
{article}{endmark}  {
                        fprintf(yyout," ARTICLE ");
                        fprintf(yyout,"%c", yytext[yyleng-1]);
                        if(yytext[yyleng-1]=='\n') yylineno++;
                        printf(":%s:%d article\n",yytext,yylineno);
                    }
{letter}*(s|es){endmark}    {
                            fprintf(yyout," PLURAL ");
                            fprintf(yyout,"%c", yytext[yyleng-1]);
                            if(yytext[yyleng-1]=='\n') yylineno++;
                            printf(":%s:%d plural\n",yytext,yylineno);
                        }
{letter}*(ly){endmark}  {
                            fprintf(yyout," ADVERB ");
                            fprintf(yyout,"%c", yytext[yyleng-1]);
                            if(yytext[yyleng-1]=='\n') yylineno++;
                            printf(":%s:%d adverb\n",yytext,yylineno);
                        }
{letter}*(ing){endmark}     {
                            fprintf(yyout," CONTINUOUS ");
                            fprintf(yyout,"%c", yytext[yyleng-1]);
                            if(yytext[yyleng-1]=='\n') yylineno++;
                            printf(":%s:%d continuous\n",yytext,yylineno);
                        }
{uppercase}{letter}*{endmark}   {
                        fprintf(yyout," NOUN ");
                        fprintf(yyout,"%c", yytext[yyleng-1]);
                        if(yytext[yyleng-1]=='\n') yylineno++;
                        printf(":%s:%d noun\n",yytext,yylineno);
                    }

{normal}+{endmark}  { 
                        fprintf(yyout," NOT_RECOGNIZED%c", yytext[yyleng-1]);
                        if(yytext[yyleng-1]=='\n') yylineno++;
                        printf(":%s:%d as it is\n",yytext,yylineno);
                    }
%%
int main(){
    yyin = fopen("Input4.txt","r");
    yyout = fopen("Output4.txt","w");
    yylex();
    fprintf(yyout, "# of lines = %d\n", yylineno);
    fclose(yyin);
    fclose(yyout);
    return 0;
}

Input4.txt:

aasdfeasdfiasoasdfuasd aeiogedaeido aeiou oeiua aeeeee aeiouuu
speaiously Addoiuea aaaaaaa ing ly

预期的Output4.txt:

VOWELS  NOT_RECOGNIZED  VOWELS  VOWELS  NOT_RECOGNIZED  VOWELS
     VOWELS   VOWELS   NOT_RECOGNIZED  CONTINUOUS  ly
# of lines = 1

我通过以下命令编译它:

flex Scanner4.l
mingw32-gcc -c lex.yy.c -o Scanner4.yy.o
mingw32-g++ -o Scanner4.yy.exe Scanner4.yy.o
Scanner4.yy

4 个答案:

答案 0 :(得分:2)

我将使用包含英语元音的这个字符类[aeiou]

[^aeiou]*[aeiou]+...

上面这样的东西可以起作用,但你说它必须包含所有元音,没有特定的顺序。所以要捕获这个意图,你需要这样的东西。

[^aeiou]*(a[^eiou]*|e[^aiou]*|i[^aeou]*|o[^aeiu]*|u[^aeio]*)...

现在你明白了吗?我们必须提供很多改动,我们必须对它们进行嵌套,以表明我们正在寻找到目前为止尚无法匹配的东西。

我们的想法是调整每次更改然后进展,好像我们可以假设我们不再寻找我们刚刚匹配的内容。只有很多正则表达式没有技巧。

但是,您需要(n-1)(n-2)(n-3)......条款。有5个元音它可以工作,但它很好......不理想。

只是为了表明这种荒谬。这是完整的正则表达式。不,我没有手工编写,我写了一个小程序来生成它。

[^aeiou]*(a[^eiou]*(e[^iou]*(i[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^iu]*(i[^u]*(u)|u[^i]*(i))|u[^io]*(i[^o]*(o)|o[^i]*(i)))|i[^eou]*(e[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^eu]*(e[^u]*(u)|u[^e]*(e))|u[^eo]*(e[^o]*(o)|o[^e]*(e)))|o[^eiu]*(e[^iu]*(i[^u]*(u)|u[^i]*(i))|i[^eu]*(e[^u]*(u)|u[^e]*(e))|u[^ei]*(e[^i]*(i)|i[^e]*(e)))|u[^eio]*(e[^io]*(i[^o]*(o)|o[^i]*(i))|i[^eo]*(e[^o]*(o)|o[^e]*(e))|o[^ei]*(e[^i]*(i)|i[^e]*(e))))|e[^aiou]*(a[^iou]*(i[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^iu]*(i[^u]*(u)|u[^i]*(i))|u[^io]*(i[^o]*(o)|o[^i]*(i)))|i[^aou]*(a[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ao]*(a[^o]*(o)|o[^a]*(a)))|o[^aiu]*(a[^iu]*(i[^u]*(u)|u[^i]*(i))|i[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ai]*(a[^i]*(i)|i[^a]*(a)))|u[^aio]*(a[^io]*(i[^o]*(o)|o[^i]*(i))|i[^ao]*(a[^o]*(o)|o[^a]*(a))|o[^ai]*(a[^i]*(i)|i[^a]*(a))))|i[^aeou]*(a[^eou]*(e[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^eu]*(e[^u]*(u)|u[^e]*(e))|u[^eo]*(e[^o]*(o)|o[^e]*(e)))|e[^aou]*(a[^ou]*(o[^u]*(u)|u[^o]*(o))|o[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ao]*(a[^o]*(o)|o[^a]*(a)))|o[^aeu]*(a[^eu]*(e[^u]*(u)|u[^e]*(e))|e[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ae]*(a[^e]*(e)|e[^a]*(a)))|u[^aeo]*(a[^eo]*(e[^o]*(o)|o[^e]*(e))|e[^ao]*(a[^o]*(o)|o[^a]*(a))|o[^ae]*(a[^e]*(e)|e[^a]*(a))))|o[^aeiu]*(a[^eiu]*(e[^iu]*(i[^u]*(u)|u[^i]*(i))|i[^eu]*(e[^u]*(u)|u[^e]*(e))|u[^ei]*(e[^i]*(i)|i[^e]*(e)))|e[^aiu]*(a[^iu]*(i[^u]*(u)|u[^i]*(i))|i[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ai]*(a[^i]*(i)|i[^a]*(a)))|i[^aeu]*(a[^eu]*(e[^u]*(u)|u[^e]*(e))|e[^au]*(a[^u]*(u)|u[^a]*(a))|u[^ae]*(a[^e]*(e)|e[^a]*(a)))|u[^aei]*(a[^ei]*(e[^i]*(i)|i[^e]*(e))|e[^ai]*(a[^i]*(i)|i[^a]*(a))|i[^ae]*(a[^e]*(e)|e[^a]*(a))))|u[^aeio]*(a[^eio]*(e[^io]*(i[^o]*(o)|o[^i]*(i))|i[^eo]*(e[^o]*(o)|o[^e]*(e))|o[^ei]*(e[^i]*(i)|i[^e]*(e)))|e[^aio]*(a[^io]*(i[^o]*(o)|o[^i]*(i))|i[^ao]*(a[^o]*(o)|o[^a]*(a))|o[^ai]*(a[^i]*(i)|i[^a]*(a)))|i[^aeo]*(a[^eo]*(e[^o]*(o)|o[^e]*(e))|e[^ao]*(a[^o]*(o)|o[^a]*(a))|o[^ae]*(a[^e]*(e)|e[^a]*(a)))|o[^aei]*(a[^ei]*(e[^i]*(i)|i[^e]*(e))|e[^ai]*(a[^i]*(i)|i[^a]*(a))|i[^ae]*(a[^e]*(e)|e[^a]*(a)))))

生成上述正则表达式的代码:

static void Main(string[] args)
{
  var vowels = new HashSet<char>("aeiou".ToCharArray());
  var sb = new StringBuilder();
  BuildRegex(vowels, sb);
  Console.WriteLine(sb);
}

private static void BuildRegex(HashSet<char> vowels, StringBuilder sb)
{
  if (vowels.Count == 0)
  {
    return;
  }
  sb.Append("[^" + string.Join(string.Empty, vowels) + "]*");
  if (vowels.Count > 0)
  {
    sb.Append('(');
    int i = 0;
    foreach (var vowel in vowels.OrderBy(x => x))
    {
      var vowels2 = new HashSet<char>(vowels);
      vowels2.Remove(vowel);
      if (i > 0)
      {
        sb.Append('|');
      }
      sb.Append(vowel);
      BuildRegex(vowels2, sb);
      i++;
    }
    sb.Append(')');
  }
}

答案 1 :(得分:1)

这种基于前瞻性的正面正则表达式适用于你:

\b(?=[[:alpha:]]*[Aa])(?=[[:alpha:]]*[Ee])(?=[[:alpha:]]*[Ii])(?=[[:alpha:]]*[Oo])(?=[[:alpha:]]*[Uu])[[:alpha:]]+\b

RegEx Demo

(?=\w*a)强制a出现在单词中,以及强制执行所有元音的其他前瞻,即a,e,i,o,u

答案 2 :(得分:1)

static int array[5];


%%
[a-zA-Z]            {
                        int i = 0;
                        for (i = 0; i < 5' i++ {
                            array[i] = 0;
                        }
                        char a;
                        i = 0;
                        for (a = yytext[i]; a != '\0'; i++) {
                            if (a == 'a') {
                                array[0] = 1;
                            }
                            if (a == 'e') {
                                array[1] = 1;
                            }
                            if (a == 'i') {
                                array[2] = 1;
                            }
                            if (a == 'o') {
                                array[3] = 1;
                            }
                            if (a == 'u') {
                                array[4] = 1;
                            }
                        }
                        if (array[0] == 1 && array[1] == 1 && array[2] == 1 && array[3] == 1 && array[4] == 1) {
                            printf("VOWELS\n");
                        }
                    }
%%

正则表达式:

a.*e.*i.*o.*u|a.*e.*i.*u.*o|a.*e.*o.*i.*u|a.*e.*o.*u.*i|a.*e.*u.*i.*o|a.*e.*u.*o.*i|a.*i.*e.*o.*u|a.*i.*e.*u.*o|a.*i.*o.*e.*u|a.*i.*o.*u.*e|a.*i.*u.*e.*o|a.*i.*u.*o.*e|a.*o.*e.*i.*u|a.*o.*e.*u.*i|a.*o.*i.*e.*u|a.*o.*i.*u.*e|a.*o.*u.*e.*i|a.*o.*u.*i.*e|a.*u.*e.*i.*o|a.*u.*e.*o.*i|a.*u.*i.*e.*o|a.*u.*i.*o.*e|a.*u.*o.*e.*i|a.*u.*o.*i.*e|e.*a.*i.*o.*u|e.*a.*i.*u.*o|e.*a.*o.*i.*u|e.*a.*o.*u.*i|e.*a.*u.*i.*o|e.*a.*u.*o.*i|e.*i.*a.*o.*u|e.*i.*a.*u.*o|e.*i.*o.*a.*u|e.*i.*o.*u.*a|e.*i.*u.*a.*o|e.*i.*u.*o.*a|e.*o.*a.*i.*u|e.*o.*a.*u.*i|e.*o.*i.*a.*u|e.*o.*i.*u.*a|e.*o.*u.*a.*i|e.*o.*u.*i.*a|e.*u.*a.*i.*o|e.*u.*a.*o.*i|e.*u.*i.*a.*o|e.*u.*i.*o.*a|e.*u.*o.*a.*i|e.*u.*o.*i.*a|i.*a.*e.*o.*u|i.*a.*e.*u.*o|i.*a.*o.*e.*u|i.*a.*o.*u.*e|i.*a.*u.*e.*o|i.*a.*u.*o.*e|i.*e.*a.*o.*u|i.*e.*a.*u.*o|i.*e.*o.*a.*u|i.*e.*o.*u.*a|i.*e.*u.*a.*o|i.*e.*u.*o.*a|i.*o.*a.*e.*u|i.*o.*a.*u.*e|i.*o.*e.*a.*u|i.*o.*e.*u.*a|i.*o.*u.*a.*e|i.*o.*u.*e.*a|i.*u.*a.*e.*o|i.*u.*a.*o.*e|i.*u.*e.*a.*o|i.*u.*e.*o.*a|i.*u.*o.*a.*e|i.*u.*o.*e.*a|o.*a.*e.*i.*u|o.*a.*e.*u.*i|o.*a.*i.*e.*u|o.*a.*i.*u.*e|o.*a.*u.*e.*i|o.*a.*u.*i.*e|o.*e.*a.*i.*u|o.*e.*a.*u.*i|o.*e.*i.*a.*u|o.*e.*i.*u.*a|o.*e.*u.*a.*i|o.*e.*u.*i.*a|o.*i.*a.*e.*u|o.*i.*a.*u.*e|o.*i.*e.*a.*u|o.*i.*e.*u.*a|o.*i.*u.*a.*e|o.*i.*u.*e.*a|o.*u.*a.*e.*i|o.*u.*a.*i.*e|o.*u.*e.*a.*i|o.*u.*e.*i.*a|o.*u.*i.*a.*e|o.*u.*i.*e.*a|u.*a.*e.*i.*o|u.*a.*e.*o.*i|u.*a.*i.*e.*o|u.*a.*i.*o.*e|u.*a.*o.*e.*i|u.*a.*o.*i.*e|u.*e.*a.*i.*o|u.*e.*a.*o.*i|u.*e.*i.*a.*o|u.*e.*i.*o.*a|u.*e.*o.*a.*i|u.*e.*o.*i.*a|u.*i.*a.*e.*o|u.*i.*a.*o.*e|u.*i.*e.*a.*o|u.*i.*e.*o.*a|u.*i.*o.*a.*e|u.*i.*o.*e.*a|u.*o.*a.*e.*i|u.*o.*a.*i.*e|u.*o.*e.*a.*i|u.*o.*e.*i.*a|u.*o.*i.*a.*e|u.*o.*i.*e.*a

只需用[a-zA-Z]替换点。

答案 3 :(得分:0)

实际上这是不可能的flex。因为,我试过以下没有运气。

  1. 起初,我尝试用全部5个运行flex程序!组合,但它立即崩溃!
  2. 然后我用简化形式的5运行flex程序!组合超过一个小时,但之后它给了fatal error!消息!
  3. 所以,我已经得出结论,决定使用flex是不可能的。