What is the regex expression for CDATA

2020-06-17 08:55发布

问题:

Hi I have an example CDATA here

<![CDATA[asd[f]]]>

and

<tag1><![CDATA[asd[f]]]></tag1><tag2><![CDATA[asd[f]]]></tag2>

The CDATA regex i have is not able to recognize this

"<![CDATA["([^\]]|"]"[^\]]|"]]"[^>])*"]]>"

this does not work too

"<![CDATA["[^\]]*[\]]{2,}([^\]>][^\]]*[\]]{2,})*">"

Will someone please give me a regex for <![CDATA[asd[f]]]>, I need to use it in Lex/Flex

: I have answered this question, please vote on my answer, thanks.

回答1:

Easy enough, it should be this:

<!\[CDATA\[.*?\]\]>

At least it works on regexpal.com



回答2:

The problem is that this is rather awkward to match with the sort of regular expressions used in lex; if you had a system that supported EREs, then you'd be able to do either:

<!\[CDATA\[(.*?)\]\]>

or

<!\[CDATA\[((?:[^]]|\](?!\]>))*)\]\]>

(The first uses non-greedy quantifiers, the second uses negative lookahead constraints. OK, it uses non-capturing parens too, but you can use capturing ones there instead; that's not so important.)

It's probably easier to handle this by using a similar strategy to the way C-style comments are handled in lex, by having one rule to match the start of the CDATA (on <![CDATA[) and put the lexer into a separate state that it leaves on seeing ]]>, while collecting all the characters in-between. This is instructive on the topic (and it seems that this is an area where flex and lex differ) and it covers all the strategies that you can take to make this work.

Note that cause of all these problems are because it's very difficult to write a rule with simple regular expressions that expresses the fact that a greedy regular expression must only match a ] if it is not followed by ]>. It's much easier to do if you've only got a two-character (or single character!) end-of-interesting-section sequence because you don't need such an elaborate state machine.



回答3:

This is the solution. The reason we need to use a START STATE is so that what ever is between <!CDATA[ and ]]> does not get match against other REGEX.

%option noyywrap
%x CDATA

%%
"<![CDATA[" { BEGIN CDATA; printf("Entering CDATA\n"); }
<CDATA>([^\]]|\n)*|.    { printf("In CDATA: %s\n", yytext); }
<CDATA>"]]>" { 
    printf("End of CDATA\n");
    BEGIN INITIAL;
}

%%
main()
{
    yylex();
}


回答4:

One note - a search for CDATA should rule out comments as well, CDATA could be embedded.
/<!(?:\[CDATA\[(.*?)\]\]|--.*?--|\[[A-Z][A-Z\ ]*\[.*?\]\])>/sg
This could be done by checking if group 1 is valid upon each match returned in a global search.



回答5:

<!\[CDATA\[\s*(?:.(?<!\]\]>)\s*)*\]\]>

Previuos answer just modified



回答6:

I believe this other SO answer may be of some help, even though they're grabbing HTML contents and is .NET.

There are other answers with various options for grabbing CDATA in that same question.

CHAD's answer:

<!\[CDATA\[(.*?)\]\]>

Matching against:

<![CDATA[asd[f]]]>

retrieves:

asd[f]

According to FlexRegEx anyways.