(Godot引擎笔记)正则表达式
在开发过程中,需要使用大量的文本文档来存储文本,这些文本会由开发者制定成不同的格式,用于资源的读取,这样便于快速开发,试想将一段上百字的对话塞进.cs脚本中用string[]保存,或者将装备道具的属性也塞进.cs脚本中,想想头都要裂开了。
那么,在外部定义好对应文本的格式后,免不了的要在程序内部进行读取,其中格式的转换又变成了一个门槛。如果是熟读编译原理可能会直接开发高级的词法分析器什么的,但是简单的话也可以用C#的正则表达式解决。
C#的正则表达式,即Regex,这个类的名称空间是System.Text.RegularExpressions。
为了演示,不妨在此设定一个.txt文档,它的内容如下:
[名字]流年夏华
[等级]114514
[职业]业余程序员
可以看到,这里使用了“[标签]内容”的格式,并以换行符作分隔。(windows里txt文档在记事本等的默认换行为\r\n,即回车符+换行符,但是有些文本编辑器为适应linux系统也支持\n换行,而在.cs脚本的string字符串中也是使用\n表示换行的,注意在文本编写时候进行鉴别)
接下来就是读取.txt文档并处理:
string[] strs =new string[3];
StreamReader reader = new StreamReader (path,System.Text.Encoding.UTF8);
Regex rex = new Regex(@"\[名字\](?<name>.*)(\r\n){0,}?");
string str = reader.ReadToEnd();
strs[0] = rex.Match(str).Groups["name"].Value;
rex = new Regex(@"\[等级\](?<level>.*)(\r\n){0,}?");
strs[1] = rex.Match(str).Groups["level"].Value;
rex = new Regex(@"\[职业\](?<profession>.*)(\r\n){0,}?");
strs[2] = rex.Match(str).Groups["profession"].Value;
这里为了简单演示使用streamreader读取外部文件并用了string[]来储存数据。实际上为了结构的完善应该定义一个用于保存内容的class例如
public class player()
{
public string name;
public int level;
public string profession;
}
以便程序内使用或者序列化之类的。
重点是正则表达式,在Regex rex = new Regex(@"\[名字\](?<name>.*)(\r\n){0,}?");中,形如@"\[名字\](?<name>.*)(\r\n){0,}?",这是使用了两个比较重要的东西,捕获命名组和惰性匹配。
捕获命名组:(?<name>.*),将匹配式.*的匹配结果以字符串值的形式存到正则表达式匹配结果的groups中的["name"]内,在后面的rex.Match(str).Groups["name"].Value;中就可以取出这个匹配结果。
惰性匹配:(\r\n){0,}?"),匹配式\r\n将匹配0次以上,但尽量地少,这在不像C#这类使用分号;和反大括号}作为结尾的强结构语言中具有重要意义(点名批评GDScript结构层次不分明),否则因为没有结尾符号导致匹配结果出现了偏差,我们作为开发者是要负责任的(阴险)。
这就是简单的读取外部文件了,但是如果要像某大型多人在线横板清关网游的脚本文件那样做到形如
[if]
[attack success]
1
[/if]
[then]
[target]
`enemy` -1
[add absolute damage]
`all` `%` 35
[/then]
的话,那就要多花功夫了。

