一个正则问题

笨笨兔兔兔兔兔 2009-11-10 02:57:09
匹配一下asp.net控件的正则表达式

我自己写了一个不太好的

语言不限js .net 或者php 都成

先来个引子

<script>
var s='<asp:Button ID="Button1" runat="server" Text="Button"></asp:Button>sds<asp:Button ID="Button5555" runat="server" Text="Button" />';
alert(s.match(/<(asp:[a-zA-Z0-9]+)[^>]+(?:runat=("|')?server\2)[^>]*\/?>(?:[^<]*<\/\1>)?/g));
</script>

这个正则有bug。。。看看谁写得比较好,我这个正则不能满足条件的地方比较多。。。

在.net区分不能发300的见谅。。。。
...全文
367 51 打赏 收藏 转发到动态 举报
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
结帖 过两天发个帖子继续讨论
mythad 2009-11-15
  • 打赏
  • 举报
回复
没那么复杂吧?匹配一下<asp:和结束?
<asp:(.*?)\s.*?</asp:\1>
呵呵,没测试哦。。。
muxrwc 2009-11-14
  • 打赏
  • 举报
回复
恩...还有预查对效率的影响也是很大的...
不过有了固化分组.可以减少好多不必要的回溯...到是挺和谐的...XD
-过客- 2009-11-14
  • 打赏
  • 举报
回复
[Quote=引用 46 楼 muxrwc 的回复:]
([""'])

(? <level>\w+)
我觉得都是有必要的...

第一个是符号配对.
第二个是嵌套时标记配对...
</asp:\k <level>>(? <-level>)
就是这里的\k反向引用需要用下\w
[/Quote]

呵呵,这个没仔细看,原来你后面还用到了k<level>

真正对匹配效率影响大的,一是量词的嵌套,再就是分支结构“|”,还有就是贪婪与非贪婪模式的运用,其它的倒还好
因为这个需求不用十分在意匹配效率,那么只要注意一下是否会存在潜在的效率陷阱也就是了,正则的侧重点可以多考虑些严谨性和可读性的问题

如果ID也是需要判断的,可以再加下判断
Regex reg = new Regex(@"(?is)<asp:(\S+)\b(?=[^>]*?runat=(['""]?)server\2)(?=[^>]*?\bid=)[^>]*/?>((?:(?!</?asp:\1).)*</asp:\1>)?");
langziqian 2009-11-14
  • 打赏
  • 举报
回复
mark
-过客- 2009-11-14
  • 打赏
  • 举报
回复
.NET中正则+委托一样可以实现任意复杂逻辑的处理,虽然绕了点弯
话题扯得有点远,谁强大无所谓,只要能够为我所用就是了

还是回到这个问题上来吧,需要兔子回答的一个问题:
什么场景下才需要使用平衡组,给个实例吧

对于复杂一点的需求,只有最合适的正则,没有最严谨的正则
而且越严谨的正则,所做的判断也就越多,逻辑也就越复杂,付出的代价也就是匹配效率和可读性的降低,存在效率陷阱的几率也就会大大的提升

muxrwc兄的正则,说下我的看法
表达式中多处使用了(?i:Exp)的语法结构,但对于一些同样需求忽略大小写的地方却没有使用,比如<asp:中的asp
多处使用降低可读性,多次处理这种语法规则是否降低解析效率,这个倒不是很清楚,不过如果是多处需要进行模式转换,不如直接在开始加个(?i)来得实际

表达式中第一个(?>没有意义,因为固化分组只有作用于匹配优先量词如*,+时才有意义

(?<-level>)没有包含任何子表达式,那么(?<level>\w+)也是没必要的,因为这里只关心是否捕获组,对于捕获的内容是不关心的,也就没有必要再为不关心的内容分配更多的内存了

还有([""'])和[^<>]+这两处是否合理,也是值得商榷的

当然,由于对需求的理解不是很透彻,我写的正则中也有很多值得商榷的地方,希望兔子和muxrwc指正,在这里很少有人讨论这一类话题的
muxrwc 2009-11-14
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 hhxx_cj 的回复:]
组合不好,帮顶学习下

我只是有种理念就是,首尾必需相同而且同时都包含ASP:
前面中必需包括ID 与 runat="server",基本上就满足了.net控件的要求了

就是组合不成下则,
特来学习一下
[/Quote]
恩...我们把ID同学给无视了= =,罪过哇...
muxrwc 2009-11-14
  • 打赏
  • 举报
回复
XD恩...

其实兔老师的需求,貌似是取所有控件,然后取它们的值,和付值.
好比
<asp:Button ID="a"...
生成出
a.Text = ...

string stra = a.Text;
类似的代码...

不过最初没概念,直接写了个多层嵌套的.
其实多层嵌套.

这个需求的话lxcnn君的式子已经可以完全满足了...

后来改了下只是追求下完美加了个 条件分支...

我那个式子...
最开始那个(?i:asp)
写多了后来和谐掉了XD

第一个固化其实只是拿它当成(?:用了.

[^ <>]+,这个是偷懒了没有用(?:(?!</?asp:...
和匹配标记里没有用(?:"[^"]*"|'[^']*'...类似XD

([""'])

(?<level>\w+)
我觉得都是有必要的...

第一个是符号配对.
第二个是嵌套时标记配对...
</asp:\k<level>>(?<-level>)
就是这里的\k反向引用需要用下\w

不过我觉得用不用命名捕获组到是没那么大差异...
感觉那东西只是带名字的Group
应该和普通的括号捕获的东西差不多...
= =,不过也没有依据只是猜的...

重要的是式子写的匹配方式是否很慢XD.

其实对于需求来说.
那个兔老师生成器
其实不用考虑
引号配对([^"'])
和标记配对(?<level>\w+)
还有自结束标记后还有结束标记(?(3)...)

因为那个是针对能通过vs生成的aspx文件的...
对于效率也没有特别高的要求.

所以就稍微写的好看一点XD.
hhxx_cj 2009-11-14
  • 打赏
  • 举报
回复
组合不好,帮顶学习下

我只是有种理念就是,首尾必需相同而且同时都包含ASP:
前面中必需包括ID 与 runat="server",基本上就满足了.net控件的要求了

就是组合不成下则,
特来学习一下
muxrwc 2009-11-13
  • 打赏
  • 举报
回复
其实功能比较强的应该是perl吧...
毕竟它正则里可以写perl代码...
虽然.net对前项预查对量词的支持.和命名捕获组确实很强大...
还支持神奇的右到左...

js里的预查bug目前貌似比较少了...
ie6的某些版本里可能会比较多...经常导致浏览器崩溃什么的...

我觉得php里的(?R)还是很和谐的...能用它匹配嵌套至少要比.net和谐...
可读性也比较高.

js里要是支持 前项预查 递归 命名捕获组 条件分支(?(name)then|else)
就和谐了XD

这个稍微严谨下比较和谐...
(?s)<asp:(\w+)[^>]+?(?i:runat)=([""'])(?i:server)\2(?:(?!/?>).)*(/)?>(?(3)|(?:(?!</asp:\1).)*</asp:\1>)

这个多加了个i..
<asp:(\w+)[^>]*(?i:runat)=([""'])(?i:server)\2(?:(?!/?>).)*   
(?>
>
(?>
<asp:\w+[^>]*/>
|
<asp:(?<level>\w+)[^>]*>
|
</asp:\k<level>>(?<-level>)
|
[^<>]+
)*
(?(level)(?!))
</asp:\1>
|
/>
-过客- 2009-11-13
  • 打赏
  • 举报
回复
因为现在的工作基本上不涉及编程,所以也很难“处心积虑”的去研究各种语言,在语言的知识上是很菜的,只是对正则比较感兴趣,一直在CSDN回答此类的问题而已

php对正则的支持,从语法上来说,和.NET基本上接近,跟语言相关的了解的不多

就兔子的需求而言,主要是看从哪方面考虑问题了

从匹配效率和需求满足的角度,至少到目前为止,我还没有看到有用平衡组的必要
如果这种代码生成器的功能,完全不用考虑匹配效率,而主要考虑的是代码的健壮性,那多考虑一些也无不可

当然,就我个人而言,目前更关心的,第一是需求满足情况,第二是匹配效率,其中也就包括语法使用的合理性

正则的强大在于它的抽象和灵活,正则是随着需求变化的,如果需求变了,正则就要跟着做相应的变动,很难给出一个固定的模式或解决方案。以前有人跟我提过正则自动生成,我认为这是不可能的,正则如果可以自动生成,那正则也就不是正则了
zyp122788 2009-11-13
  • 打赏
  • 举报
回复
帮顶
  • 打赏
  • 举报
回复
一段代码生成器的一部分,用了这个正则,能节约大概30行左右的代码量。。。。之所以用muxrwc的

正则是因为我们住一起。。。基本不会用别人的代码的,所以我才说帖子是拿来讨论的,见谅

主要感觉是这个需求如果要扩展了,很bt也很好玩。。。。当然能给出不错的正则或方案的分不会少
  • 打赏
  • 举报
回复
顺便回馈一下大家,我为什么要写这个...


<%--
Name:
Author:
Description:
--%>
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="PageBase.cs" Inherits="PageBase" Debug="True" Description="Template description here." %>
<%@ Property Name="NameSpace" Type="String" Optional="True" Category="Context" Default="ProjectManage" Description="The namespace to use for this class" %>
<%@ Property Name="IsInitValue" Type="System.Boolean" Default="True" Optional="True" Category="Booleans" Description="Init Value" %>
<%@ Property Name="IsSubmitValue" Type="System.Boolean" Default="True" Optional="True" Category="Booleans" Description="Init Value" %>
<%@ Assembly Name="System.Data" %>
<%@ Assembly Src="Common.cs" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="System.Design" %>

<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="TX.Template.Util" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<% AnalysisPage();%>
using <%= NameSpace %>.Entity;
using <%= NameSpace %>.Logic;

protected void dataBind()
{
<%=CreateInitValue()%>
}

protected void btnSumit()
{
<%=CreateSubmitValue()%>
}



<script runat="template">
private string filename = string.Empty;
private IDictionary<string,string> controlList = new Dictionary<string,string>();
private IDictionary<string, string> dicInitControl = new Dictionary<string, string>();
private IDictionary<string, string> dicSubmitControl = new Dictionary<string, string>();
private IDictionary<string, int> dicControlHeadLen = new Dictionary<string, int>();
private Hashtable htTable = new Hashtable();
private TableSchemaCollection _sourceTables;

public string CreateInitValue()
{
StringBuilder sbInitText = new StringBuilder();
foreach(string tablename in htTable.Keys)
{
sbInitText.Append(tablename + "Entity " + GetCamelCaseName(tablename) + "Entity = new " + tablename + "Entity();\r\n");
}
foreach(KeyValuePair<string, string> kvp in ControlList)
{
//Debug.Print(kvp.Value.ToLower());
if(!dicInitControl.ContainsKey(kvp.Value.ToLower()))
{
continue;
}
else
{
foreach(string tablename in htTable.Keys)
{
string controlID = kvp.Key;
string columnLowName = kvp.Key.Substring(dicControlHeadLen[kvp.Value]).ToLower();
Debug.Print(columnLowName);
Hashtable htTemp = ((Hashtable)(htTable[tablename]));
if(htTemp.ContainsKey(columnLowName))
{
string templateString = dicInitControl[kvp.Value];
templateString = templateString.Replace("{$ID}",controlID);
templateString = templateString.Replace("{$Value}",GetCamelCaseName(tablename)+"Entity."+((ColumnSchema)(htTemp[columnLowName])).Name + ".ToString()");
sbInitText.Append(" " + templateString + "\r\n");
}
}
}
}
return sbInitText.ToString();
}

public string CreateSubmitValue()
{
StringBuilder sbSubmitText = new StringBuilder();
StringBuilder sbSubmitDataText = new StringBuilder();
foreach(string tablename in htTable.Keys)
{
sbSubmitText.Append(tablename + "Entity " + GetCamelCaseName(tablename) + "Entity = new " + tablename + "Entity();\r\n");
}
foreach(KeyValuePair<string, string> kvp in ControlList)
{
if(!dicSubmitControl.ContainsKey(kvp.Value))
{
continue;
}
else
{
foreach(string tablename in htTable.Keys)
{
string controlID = kvp.Key;
string columnLowName = kvp.Key.Substring(dicControlHeadLen[kvp.Value]).ToLower();
Hashtable htTemp = ((Hashtable)(htTable[tablename]));
if(htTemp.ContainsKey(columnLowName))
{
string templateString = dicSubmitControl[kvp.Value];
templateString = templateString.Replace("{$ID}",controlID);
templateString = templateString.Replace("{$Variable}","string " + GetCamelCaseName(((ColumnSchema)(htTemp[columnLowName])).Name));
sbSubmitText.Append(" " + templateString + "\r\n");

sbSubmitDataText.Append(" " + GetCamelCaseName(tablename)+"Entity."+((ColumnSchema)(htTemp[columnLowName])).Name + " = ");
sbSubmitDataText.Append(GetCSharpVariableType(((ColumnSchema)(htTemp[columnLowName])), GetCamelCaseName(((ColumnSchema)(htTemp[columnLowName])).Name)));
sbSubmitDataText.Append(";\r\n");
}
}
}
}
return sbSubmitText.ToString() + sbSubmitDataText.ToString();
}

private void Init()
{
dicInitControl.Add("label", "{$ID}.Text = {$Value};");
dicInitControl.Add("textbox", "{$ID}.Text = {$Value};");
dicInitControl.Add("checkboxlist", "{$ID}.SelectedValue = {$Value};");
dicInitControl.Add("radiobuttonlist", "{$ID}.SelectedValue = {$Value};");
dicInitControl.Add("dropdownlist", "{$ID}.SelectedValue = {$Value};");

//dicSubmitControl.Add("label", "{$Variable} = {$ID}.Text;");
dicSubmitControl.Add("textbox", "{$Variable} = {$ID}.Text;");
dicSubmitControl.Add("checkboxlist", "{$Variable} = {$ID}.SelectedValue;");
dicSubmitControl.Add("radiobuttonlist", "{$Variable} = {$ID}.SelectedValue;");
dicSubmitControl.Add("dropdownlist", "{$Variable} = {$ID}.SelectedValue;");

dicControlHeadLen.Add("label", 3);
dicControlHeadLen.Add("textbox", 3);
dicControlHeadLen.Add("checkboxlist", 3);
dicControlHeadLen.Add("radiobuttonlist", 3);
dicControlHeadLen.Add("dropdownlist", 3);

}

private void InitTable()
{
foreach ( TableSchema table in _sourceTables )
{
Hashtable htTemp = new Hashtable();
foreach(ColumnSchema column in table.Columns)
{
htTemp.Add(column.Name.ToLower(),column);
}
htTable.Add(table.Name,htTemp);
}
}

[Category("01b. Filter by Individual Objects - Optional")]
[Description("The tables you wish to generate, if you do not select any SourceTables or SourceViews, and SourceDatabase is completed, then the entire database will be generated.")]
[CodeTemplateProperty(CodeTemplatePropertyOption.Optional)]
public TableSchemaCollection SourceTables
{
get
{
if (this._sourceTables != null && this._sourceTables.Count > 0 )
return this._sourceTables;
else
return null;
}
set
{
this._sourceTables = value;
}
}

[EditorAttribute(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Optional]
[Category("ChooseFile")]
[Description("choose file.")]
public string PageFilename
{
get
{
return filename;
}
set
{
filename = value;
}
}

public void CreatePage()
{

}

public IDictionary<string,string> ControlList
{
get
{
return controlList;
}
}

private void ChooseControls(string pageContent)
{
Regex r = new Regex(@"
<(?i:asp):(\w+)[^>]*(?i:runat)=([""'])(?i:server)\2(?:(?!/?>).)*
(?>
>
(?>
<asp:\w+[^>]*/>
|
<asp:(?<level>\w+)[^>]*>
|
</asp:\k<level>>(?<-level>)
|
[^<>]+
)*
(?(level)(?!))
</asp:\1>
|
/>
)
", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
MatchCollection mc = r.Matches(pageContent);

foreach (Match i in mc)
{
string controlNameValue = GetID(i.Value);
string controlTypeValue = GetControlType(i.Value);
if(controlNameValue != string.Empty)
{
//Debug.Print(controlNameValue);
this.ControlList.Add(controlNameValue, controlTypeValue);
}
}
}

public string GetControlType(string controlHTML)
{
string retString=string.Empty;
Regex re = new Regex(@"(?<=asp:)([a-zA-Z0-9]+)(?<=\s*)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
MatchCollection mc = re.Matches(controlHTML);
if(mc.Count>0)
{
retString = mc[0].ToString().ToLower();
}
return retString;
}

public string GetID(string controlHTML)
{
string retString=string.Empty;
Regex re = new Regex(@"(?<=id=\s*""?)[a-zA-Z0-9]+(?<=""*)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
MatchCollection mc = re.Matches(controlHTML);
if(mc.Count>0)
{
retString = mc[0].ToString();
}
return retString;
}

public void AnalysisPage()
{
InitTable();
Init();
StreamReader sr=new StreamReader(filename);
string pageContent=sr.ReadToEnd();
ChooseControls(pageContent);

}


</script>

  • 打赏
  • 举报
回复
关注到是不少, c++里的正则可麻烦了...我记得我在3,4年前做isapi的时候打算用正则,

结果引用了一下vbs的正则,直接导致iis崩溃,当时我还想呢,那个有名的urlrewrite怎么实现的

后来因为需求变了,也就一直没研究,最近发现原来boost库中有正则,不过不知道boost又能支持多少

最近楼上的小兄弟写了个正则工具等他完善了,再叫我家另一个兄弟美化美化,然后给大家show show

我看了一下lxcnn兄台也是看过精通正则表达式那本书吧,呵呵...基本书上都是用perl做的例子

不知道你看没看过php对正则的支持...
-过客- 2009-11-13
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 liuxiaoyi666 的回复:]
其实是想大家一起讨论一下的,正则其实有很多很好玩的东西在里面,一起讨论一下比较热闹,当年 梅子 emu 秋水他们经常一起讨论的,梅子每每提起这个,总会说到秋水当时的方案。。。哎
[/Quote]

2003年还没有接触编程,更不要说正则了。。。

正则很强大,这一点已经引起了程序语言设计者的重视,但却没有引起开发人员的重视,至少目前在国内是这样的

正则发展到现在,出现的分支太多了,而各语言之间对正则实现的差异化,在一定程度上促进了正则的发展,但却在另一层面上,阻碍了正则在程序员中的普及

曾经的曾经,perl是对正则支持最好的语言,不过现在,综合来看,应该是.NET对正则的支持最强大了,平衡组很有代表性
当然,其它语言中的正则也有值得借鉴的,比如Java中的占有优先量词++,*+等等就是非常值得借鉴的一种语法

JavaScript中最大的限制在于没有提供对逆序环视
(?<=Exp)、(?<!Exp)
的支持,对顺序环视(?=Exp)的支持也不是很稳定,以前曾经测出过一个bug,不过时间太久,忘记是怎么一回事了;同时也不支持命名捕获组,对于普通捕获组的支持也不好
还有就是同样为JavaScript程序,在不同的浏览器解析引擎下,匹配行为也有细微的差别,比如小数点“.”在IE下可以匹配“\r”,而在Firefox、Chrome等浏览器下却无法匹配

Java中目前不支持命名捕获组,据说7.0会提供支持
还有就是Java中不支持类似于.NET中字符串前加@来忽略转义,这使得写出来的正则显得很笨拙

很想和大家探讨一下正则相关的知识,不过目前来说,国内这方面讨论的比较少,主要也是因为被关注的少
happy664618843 2009-11-12
  • 打赏
  • 举报
回复
不知道怎么做 学 习 友情帮顶
phper2008 2009-11-12
  • 打赏
  • 举报
回复
不错,学习下!
dengxiao1981 2009-11-12
  • 打赏
  • 举报
回复
绑定
hy_lihuan 2009-11-12
  • 打赏
  • 举报
回复
难得过客还过来解决问题
加载更多回复(30)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧