平常喜欢写点小东西玩玩,既可以娱乐自己满足自己的虚荣心,又可以方便工作和学习,今天且拿出一个来,与大家一起分享!
言归正传,先看看需求,有这样一串字符串 abc,def,ghi,jkl,mno 我想把它转为
<td>abc</td><td>def</td><td>ghi</td><td>jkl</td><td>mno</td>
也许这很简单,因为毕竟只有几条而已,但是如果这句话有上百个单元呢,我想大部分程序员应该和我一样,写个小程序来帮我们实现这个功能,那问题来了,挖掘机技……(好吧,习惯了),如果我现在要把上面那句转为 abc|def|ghi|jkl|mno 又当如何,再写一个程序? No!
先看看我是怎么做的:
首先请无视工具栏那几个按钮,没啥作用(后面会提到),左侧两个文本框,上面的是输入,下面的是输出,右侧,是程序的核心部分,一个命令输入文本框(类似于DOS窗口)(本人开发的吆^_^),带有自动提示(是我Kiang来的),也许会有人问我,为啥做成命令行的,呵呵,装逼不需要解释。
这里面实现了几中常见字符串处理的方式,但是你以为这就完了吗,然而并没有,哥这个是带有脚本功能的,也就是说,这个不起眼的程序是可以通过脚本来扩展的。
该程序使用了 CSScript (英文的,别急着点,看完这篇先),CSScript 是(奉上我渣渣的中文翻译)
CS-Script (读作 C sharp script) 使用ECMA标准的C#作为编程语言并基于 CLR (Common Language Runtime) 的脚本系统 . CS-Script 目前支持 Windows 和 Linux 的 CLR (MS .NET4.0 and Mono).
简单来说就是通过.Net程序动态加载CS-Script,使用方式和C/C++ 调用的Lua等语言的方式一样,当然我是猜的,我也不清楚,这里先看看CS-Script的使用方式,
首先引用程序集
接下这一步是非必要的,可以根据自己的需要来调整。在这里我们要定义脚本所要继承的类和要实现的接口,:
代码分别如下:
BaseCommand.cs 文件
1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Linq; 5 using System.Text; 6 using System.Windows.Forms; 7 namespace StringTools 8 { 9 /// <summary> 10 /// 脚本所要集成的父类,提供一些基本方法 11 /// </summary> 12 public class BaseCommand 13 { 14 15 /// <summary> 16 /// 窗体主体,方便在以后开发中可以通过脚本方式直接调用窗体控件,如上面没实现任何功能的按钮 17 /// </summary> 18 public FrmMain CurrMainForm { get; set; } 19 /// <summary> 20 /// 用于记忆当前命令行控件的字体颜色 21 /// </summary> 22 public Color DefaultColor { get; set; } 23 /// <summary> 24 /// 命令行字典 25 /// </summary> 26 public Dictionary<string, string> CommandList { get; set; } 27 28 /// <summary> 29 /// 向输出文本框写入文本 30 /// </summary> 31 /// <param name="message"></param> 32 public virtual void Print(string message) 33 { 34 CurrMainForm.txtOutput.Text = message; 35 CurrMainForm.txtCon.Write(); 36 } 37 38 /// <summary> 39 /// 清理命令行控件内容 40 /// </summary> 41 public void ClearCommand() 42 { 43 CurrMainForm.txtCon.Clear(); 44 } 45 46 /// <summary> 47 /// 向命令行控件写信息 48 /// </summary> 49 /// <param name="msg"></param> 50 public virtual void WriteCommand(string msg = "") 51 { 52 CurrMainForm.txtCon.Write(msg); 53 } 54 55 /// <summary> 56 /// 向命令行控件写信息,并带有字体颜色 57 /// </summary> 58 /// <param name="msg"></param> 59 /// <param name="fontColor"></param> 60 public virtual void WriteCommand(string msg, Color fontColor) 61 { 62 CurrMainForm.txtCon.SelectionColor = fontColor; 63 CurrMainForm.txtCon.Write(msg); 64 CurrMainForm.txtCon.SelectionColor = DefaultColor; 65 } 66 67 /// <summary> 68 /// 初始化5个按钮的单击事件 69 /// </summary> 70 internal void IniteBtn() 71 { 72 CurrMainForm.btnNo1.Click += OnbtnNo_Click; 73 CurrMainForm.btnNo2.Click += OnbtnNo_Click; 74 CurrMainForm.btnNo3.Click += OnbtnNo_Click; 75 CurrMainForm.btnNo4.Click += OnbtnNo_Click; 76 CurrMainForm.btnNo5.Click += OnbtnNo_Click; 77 } 78 /// <summary> 79 /// 单击事件方法 80 /// </summary> 81 /// <param name="sender"></param> 82 /// <param name="e"></param> 83 private void OnbtnNo_Click(object sender, EventArgs e) 84 { 85 BtnClick(int.Parse((sender as ToolStripButton).Tag.ToString())); 86 } 87 /// <summary> 88 /// 可重载方法,方便脚本中处理对应的事件方法 89 /// </summary> 90 /// <param name="index"></param> 91 public virtual void BtnClick(int index) 92 { 93 94 } 95 } 96 } View Code
ICommand.cs 文件
1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Linq; 5 using System.Text; 6 7 namespace StringTools 8 { 9 /// <summary> 10 /// 脚本所要是现实的接口 11 /// </summary> 12 public interface ICommand 13 { 14 /// <summary> 15 /// 命令执行方法 16 /// </summary> 17 /// <param name="cmd"></param> 18 /// <param name="inputText"></param> 19 void Exec(string cmd, string inputText); 20 /// <summary> 21 /// 帮助文档方法 22 /// </summary> 23 /// <returns></returns> 24 string HelpDoc(); 25 /// <summary> 26 /// 命令列表,继承 BaseCommand 后默认实现 27 /// </summary> 28 Dictionary<string, string> CommandList { get; } 29 /// <summary> 30 /// 主界面 ,继承 BaseCommand 后默认实现(脚本设置无效) 31 /// </summary> 32 FrmMain CurrMainForm { get; set; } 33 /// <summary> 34 /// 命令行默认字体颜色,继承 BaseCommand 后默认实现(脚本设置无效) 35 /// </summary> 36 Color DefaultColor { get; set; } 37 } 38 } View Code
当定义完毕之后就可以开始写脚本代码了
ExecScript.cs 是今天这篇文档的主角,而StringExtension.cs是一些对string类型的扩展方法实现的文件
在开始介绍之前,先对CS-Script指令做一点介绍,
这些指令要放在脚本文件的前面(类似于注释一样),好接下来就是ExecScript.cs文件的内容了
1 //css_import StringExtension.cs 2 3 using System; 4 using System.Collections.Generic; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Text.RegularExpressions; 9 using System.Windows.Forms; 10 namespace StringTools 11 { 12 public class ExecScript : BaseCommand, ICommand 13 { 14 public ExecScript() 15 { 16 BuildList(); 17 } 18 19 Random rand=new Random (DateTime.Now.Millisecond); 20 21 //生成命令列表,用于自动提示 22 private void BuildList() 23 { 24 CommandList = new Dictionary<string, string>(); 25 CommandList.Add("rep", "rep [1] [2]/r/n -- 字符串替换,[1] 目标,[2] 替换内容"); 26 CommandList.Add("repregx", "repregx [1] [2]/r/n -- 字符串替换,[1] 正则表达式 ,[2] 替换内容"); 27 CommandList.Add("idx", "idx [1]/r/n -- 顺序查找字符位置,[1] 字符"); 28 CommandList.Add("ldx", "ldx [1]/r/n -- 逆序查找字符位置,[1] 字符"); 29 CommandList.Add("len", "len/r/n -- 字符串长度"); 30 CommandList.Add("spl", "spl [1]/r/n -- 字符串按指定字符分为行,[1]字符 "); 31 CommandList.Add("spe", "spe [1] [2] [3] [4]/r/n -- 字符串替换扩展,[1] 目标,[2] 左侧 [3] 右侧 [4] 替换内容"); 32 CommandList.Add("sbr", "sbr/r/n -- 字符串封装StringBuilder"); 33 CommandList.Add("regex", "regex [1]/r/n -- 正则表达式匹配"); 34 CommandList.Add("popo", "popo/r/n -- 这都是泡沫"); 35 36 CommandList.Add("print", "print [1]/r/n -- 向输出打印数据"); 37 CommandList.Add("cls", "cls/r/n -- 清理命令区域内容"); 38 CommandList.Add("?", "?/r/n -- 帮助 同 “help”"); 39 CommandList.Add("help", "help/r/n -- 帮助 同 “?”"); 40 CommandList.Add("cmdlst", "cmdlst/r/n -- 列出当前可用的命令"); 41 CommandList.Add("ver", "ver/r/n -- 获取脚本版本"); 42 } 43 44 45 //命令执行入口 46 public void Exec(string cmd, string inptuText) 47 { 48 if (string.IsNullOrEmpty(cmd)) 49 { 50 WriteCommand(); 51 return; 52 } 53 54 string[] arr = cmd.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 55 56 if (arr[0] != "regex") 57 { 58 for (int i = 1; i < arr.Length; i++) 59 { 60 if (arr[0] == "repregx" && i == 1) 61 continue; 62 arr[i] = arr[i].Replace("//s", " ").Replace("//t", "/t") 63 .Replace("//d", "").Replace("//n", "/n") 64 .Replace("//r", "/r"); 65 } 66 } 67 68 try 69 { 70 switch (arr[0]) 71 { 72 case "rep": 73 Print(inptuText.Replace(arr[1], arr[2])); 74 break; 75 case "idx": 76 Print(inptuText.IndexOf(arr[1]).ToString()); 77 break; 78 case "ldx": 79 Print(inptuText.LastIndexOf(arr[1]).ToString()); 80 break; 81 case "len": 82 Print(inptuText.Length.ToString()); 83 break; 84 case "spl": 85 Print(inptuText.SplitForRow(new char[] { arr[1][0] })); 86 break; 87 case "spe": 88 Print(inptuText.SplitWithOp(arr[1].ToCharArray(), arr[2], arr[3], arr[4])); 89 break; 90 case "sbr": 91 Print(inptuText.ToStringBuilder()); 92 break; 93 case "popo": 94 StringBuilder popSbr=new StringBuilder(); 95 for (int pop1 = 0; pop1 < 1000; pop1++) 96 { 97 var popoRand=rand.Next(0,9); 98 switch (popoRand-1) 99 { 100 case 0:popSbr.Append(".");break; 101 case 1:popSbr.Append("。");break; 102 case 2:popSbr.Append("o");break; 103 case 3:popSbr.Append("O");break; 104 case 4:popSbr.Append("0");break; 105 case 5:popSbr.Append("゜");break; 106 case 6:popSbr.Append("○");break; 107 case 7:popSbr.Append("O");break; 108 case 8:popSbr.Append("〇");break; 109 } 110 if (pop1 % 50 == 49) 111 { 112 popSbr.AppendLine(); 113 } 114 115 } 116 Print(popSbr.ToString()); 117 break; 118 case "regex": 119 var ms = Regex.Matches(inptuText, arr[1]); 120 StringBuilder regxsbr = new StringBuilder(); 121 foreach (Match i in ms) 122 { 123 regxsbr.AppendLine("---------------------------"); 124 regxsbr.AppendFormat("{0}/r/n", i.Value); 125 foreach (Group j in i.Groups) 126 { 127 regxsbr.AppendFormat(" {0}/r/n", j.Value); 128 } 129 } 130 131 Print(regxsbr.ToString()); 132 break; 133 case "repregx": 134 135 Print(Regex.Replace(inptuText, arr[1], arr[2])); 136 break; 137 138 139 case "cmdlst": 140 StringBuilder cmdListStr = new StringBuilder(); 141 var cmdList=CommandList.Keys.ToArray(); 142 for (int i = 0; i <cmdList.Length; i++) 143 { 144 cmdListStr.Append(cmdList[i].PadRight(10, ' ')); 145 if (i%6 == 5) 146 { 147 cmdListStr.AppendLine(); 148 } 149 } 150 WriteCommand(cmdListStr.ToString()); 151 break; 152 case "print": 153 Print(arr[1]); 154 break; 155 case "cls": 156 ClearCommand(); 157 break; 158 case "?": 159 case "help": 160 if (arr.Length == 2 && CommandList.Keys.Contains(arr[1])) 161 { 162 WriteCommand(CommandList[arr[1]]); 163 } 164 else 165 { 166 WriteCommand(HelpDoc()); 167 } 168 break; 169 case "ver": 170 WriteCommand(VersionName()); 171 break; 172 default: 173 WriteCommand("未知的命令!", Color.DarkGreen); 174 break; 175 } 176 177 } 178 catch (IndexOutOfRangeException ex) 179 { 180 WriteCommand("参数错误!Eg:/r/n" + CommandList[arr[0]], Color.Tomato); 181 } 182 catch (Exception ex1) 183 { 184 WriteCommand("错误:" + ex1.Message, Color.Tomato); 185 } 186 } 187 188 //获取帮助文档 189 public string HelpDoc() 190 { 191 StringBuilder sbr = new StringBuilder(); 192 sbr.AppendLine("帮助功能"); 193 sbr.AppendLine("------------------------------------"); 194 sbr.AppendLine("[命令]"); 195 foreach (var i in CommandList) 196 { 197 sbr.AppendLine(i.Value); 198 } 199 sbr.AppendLine(); 200 sbr.AppendLine("[注意]"); 201 sbr.AppendLine("命令与各参数使用空格隔开,如果需要使用空格,请使用“//s”"); 202 sbr.AppendLine(); 203 sbr.AppendLine(); 204 sbr.AppendLine("------------------------------------"); 205 sbr.AppendLine(VersionName()); 206 207 return sbr.ToString(); 208 } 209 210 public string VersionName() 211 { 212 StringBuilder sbr = new StringBuilder(); 213 sbr.Append("字符串处理工具 - 脚本 v0.2 [墨云软件]"); 214 return sbr.ToString(); 215 216 } 217 218 /// <summary> 219 /// 工具栏按钮 220 /// </summary> 221 /// <param name="index"></param> 222 public override void BtnClick(int index) 223 { 224 MessageBox.Show(index.ToString()); 225 } 226 227 } 228 } View Code
可以看到第一行我使用了
//css_import StringExtension.cs 来引入了string扩展方法的脚本
接下来就是最后的脚本加载到软件中的部分了
1 /// <summary> 2 /// 初始化脚本 3 /// </summary> 4 /// <returns></returns> 5 private bool IniteScrpit() 6 { 7 8 9 try 10 { 11 12 //脚本初始化方式 注意 脚本必须实现ICommand 接口 13 AsmHelper asm = new AsmHelper(CSScript.Load(Config.ScriptPath,null,true)); 14 cmdEntity = (ICommand)asm.CreateObject("*"); 15 16 cmdEntity.CurrMainForm = this; 17 ((BaseCommand)cmdEntity).IniteBtn(); 18 cmdEntity.DefaultColor = txtCon.ForeColor; 19 return true; 20 } 21 catch (Exception ex) 22 { 23 MessageBox.Show( "脚本加载错误:/r/n"+ex.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error); 24 Environment.Exit(0); 25 return false; 26 } 27 28 29 }
代码下载地址:
http://pan.baidu.com/s/1eQyht9g
感谢的阅览,如有好的意见或建议欢迎不吝赐教。
最后宣传一下自己的抓包软件
NetAnalyzer下载地址
NetAnalzyer交流群:39753670 (PS 只提供交流平台,群主基本不说话^_^)