活用regex的例子

在reddit推荐的文章上看到的。下面的代码在CMD窗口下运行通过。如果在BASH下面运行,单引号和双引号要对调。

perl - wle " print'prime'if(1xshift)!~/^1?$|^(11+?)\1+$/ " < 任意一个数 >

Python的代码是:

import re
def is_prime(num):
return not re.match(r " ^1?$|^(11+?)\1+$ " , " 1 " * num)

Ruby有Perl的血脉,所以代码和Perl版本几乎一样(其实无所谓,反正关键都是同样一段regex):

ruby - e " puts'prime'if(' 1' *ARGV.shift.to_i)!~/^1?$|^(11+?)\1+$/ " <任意一个数>

判断方法很有意思。把给出的数用一进制表示。比如5就是11111。然后从2开始一个数一个数地看这段表示中1的数目是否是其中任意一个的数的倍数。比如说当给出的数是4,则对应的表示是1111。那么1111匹配^11\1,也就是说它匹配^(11+?)\1+$。那么它是2的倍数。所以4不是质数。而当给出的数是7时,对应的表示是1111111。那这葛字符串不能匹配11\1+,也不能匹配111\1+,...,也不能匹配1111111\1+,所以7是质数。

解释一下regex的构造:
^1?$,匹配空的字串或者"1"。换句话说,0和1不是质数。

(11+?)\1+,(11+?)匹配长度为2或者2以上且形如"11.....111"的字串。注意那个问号,说明匹配点到即止,不是贪婪匹配。这点很重要,不然(11+)可以匹配所有长度大于2且形如"11...1"的字串。回溯参考符\1表示匹配之前匹配到的字串,也就是(11+?)了。点睛之笔来了:\1+表示匹配一到多个之前匹配到的(11+?)。换句话说,匹配长度为N*M的字串,这里N大于0,而M就是(11+?)匹配上的长度。因为Perl的regex自动回溯,所以(11), (111), (1111)...都会被自动尝试。

这段代码除了漂亮精巧值得欣赏,以及可以用来玩味理解regex以外,还有什么价值呢?效率?显然不够高。实用性?恐怕也没有多少。不过,这段代码隐含了重要的编程思想:编码。我们可以把一段问题用某种方式表达出来,再根据这段表达谋求解决之道。这种方法看似简单,却应用广泛。我们可以把各式自动机用字符串表示出来,由此相对容易地发现很多深刻的性质。我们把系统规格用状态机描述出来,再把状态机用逻辑公式表达出来,于是我们可以自动验证系统规格有没有逻辑上的缺陷,有没有安全问题。进一步说,我们赖以为生的整个计算体系也是建立编码的基础上:所有的数据所有的命令最终被转换为01表示。计算理论基础更离不开编码。从歌德尔定理到图灵机理论到自动机理论到计算复杂性,不知多少伟大的证明依靠编码。

还有一点好玩儿的。Perlregex匹配是NP-Complete的问题。这里有证明。数独(sudoku)也是NP-Complete问题。所以我们可以通过写出regex表达式来解决数独猜谜。关键还是把数独的题面转化成可以匹配的字串。牛人Abigail给出了一个方案Abigail也是上面判断质数代码的作者。呵呵,其实我们也可以把regex配备问题转换成数独问题,然后用数独程序来实现匹配。哪位闲得不行的老大可以去试试。

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace BeamSectionPlugin { public class BeamSectionExtractor { [CommandMethod("ExtractBeamSections")] public void ExtractBeamSections() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 选择所有图层上的梁文字 PromptSelectionOptions selOpts = new PromptSelectionOptions(); selOpts.MessageForAdding = "\n选择包含梁尺寸的文字对象: "; PromptSelectionResult selResult = ed.GetSelection(selOpts); if (selResult.Status != PromptStatus.OK) return; // 存储截面尺寸统计 Dictionary<string, int> sizeCounts = new Dictionary<string, int>(); Regex sizePattern = new Regex(@"(\d{1,4})\s*[xX×]\s*(\d{1,4})"); using (Transaction tr = db.TransactionManager.StartTransaction()) { // 遍历选中对象 foreach (SelectedObject selObj in selResult.Value) { if (selObj == null) continue; Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity; if (ent is DBText text) { ProcessText(text.TextString, sizePattern, sizeCounts); } else if (ent is MText mtext) { ProcessText(mtext.Contents, sizePattern, sizeCounts); } } // 生成统计表 if (sizeCounts.Count > 0) { CreateStatisticsTable(ed, sizeCounts); } else { ed.WriteMessage("\n未找到梁截面尺寸!"); } tr.Commit(); } } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } } private void ProcessText(string text, Regex pattern, Dictionary<string, int> sizeCounts) { MatchCollection matches = pattern.Matches(text); foreach (Match match in matches) { if (match.Groups.Count == 3) { string size = $"{match.Groups[1].Value}×{match.Groups[2].Value}"; if (sizeCounts.ContainsKey(size)) { sizeCounts[size]++; } else { sizeCounts.Add(size, 1); } } } } private void CreateStatisticsTable(Editor ed, Dictionary<string, int> sizeCounts) { // 计算线荷载并排序 var sortedSizes = sizeCounts.Select(kv => new { Size = kv.Key, Count = kv.Value, Area = CalculateArea(kv.Key), LineLoad = CalculateLineLoad(kv.Key) }).OrderBy(item => item.LineLoad).ToList(); Database db = ed.Document.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 提示用户指定表格插入点 PromptPointOptions pOpts = new PromptPointOptions("\n指定表格插入点: "); PromptPointResult pResult = ed.GetPoint(pOpts); if (pResult.Status != PromptStatus.OK) return; Table table = new Table(); table.SetDatabaseDefaults(); table.Position = pResult.Value; // 设置表格尺寸 int numRows = sortedSizes.Count + 2; // 数据行 + 表头行 + 备注行 int numCols = 5; table.SetSize(numRows, numCols); // 设置字体高度为500mm const double textHeight = 500.0; // 设置列宽 double[] colWidths = { 1500, 2500, 1500, 2000, 2500 }; for (int col = 0; col < numCols; col++) { table.Columns[col].Width = colWidths[col]; } // 设置行高(根据字体高度自动调整) double rowHeight = textHeight * 1.8; for (int row = 0; row < numRows; row++) { table.Rows[row].Height = rowHeight; } // 设置所有单元格文本高度和居中 for (int row = 0; row < numRows; row++) { for (int col = 0; col < numCols; col++) { table.Cells[row, col].TextHeight = textHeight; table.Cells[row, col].Alignment = CellAlignment.MiddleCenter; } } // 设置表头 table.Cells[0, 0].TextString = "序号"; table.Cells[0, 1].TextString = "梁截面尺寸(mm)"; table.Cells[0, 2].TextString = "出现数量"; table.Cells[0, 3].TextString = "截面面积(㎡)"; table.Cells[0, 4].TextString = "施工线荷载(kN/m)"; // 填充数据 for (int i = 0; i < sortedSizes.Count; i++) { int row = i + 1; var item = sortedSizes[i]; table.Cells[row, 0].TextString = (row).ToString(); table.Cells[row, 1].TextString = item.Size; table.Cells[row, 2].TextString = item.Count.ToString(); table.Cells[row, 3].TextString = item.Area.ToString("F4"); table.Cells[row, 4].TextString = item.LineLoad.ToString("F2"); } // 添加备注行 int lastRow = numRows - 1; table.Cells[lastRow, 0].TextString = "备注:表中施工线荷载值仅做参考"; // 合并备注行单元格 - 使用正确的方法 // 创建要合并的单元格范围 table.MergeCells( minRow: lastRow, minColumn: 0, maxRow: lastRow, maxColumn: numCols - 1 ); // 设置表格边框 table.GenerateLayout(); // 添加到模型空间 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); tr.Commit(); ed.WriteMessage("\n梁截面统计表创建完成!"); } } private double CalculateArea(string size) { string[] dims = size.Split('×'); if (dims.Length == 2 && double.TryParse(dims[0], out double width) && double.TryParse(dims[1], out double height)) { return (width / 1000) * (height / 1000); // 转换为平方米 } return 0; } private double CalculateLineLoad(string size) { double area = CalculateArea(size); // 混凝土容重25kN/m³ + 模板荷载2kN/m return area * 25 + 2.0; } } } CS1739“MergeCells”的最佳重载没有名为“minRow”的参数
最新发布
07-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值