(Godot引擎筆記)正則表達式
在開發(fā)過程中,需要使用大量的文本文檔來存儲文本,這些文本會由開發(fā)者制定成不同的格式,用于資源的讀取,這樣便于快速開發(fā),試想將一段上百字的對話塞進.cs腳本中用string[]保存,或者將裝備道具的屬性也塞進.cs腳本中,想想頭都要裂開了。
那么,在外部定義好對應(yīng)文本的格式后,免不了的要在程序內(nèi)部進行讀取,其中格式的轉(zhuǎn)換又變成了一個門檻。如果是熟讀編譯原理可能會直接開發(fā)高級的詞法分析器什么的,但是簡單的話也可以用C#的正則表達式解決。
C#的正則表達式,即Regex,這個類的名稱空間是System.Text.RegularExpressions。
為了演示,不妨在此設(shè)定一個.txt文檔,它的內(nèi)容如下:
[名字]流年夏華
[等級]114514
[職業(yè)]業(yè)余程序員
可以看到,這里使用了“[標簽]內(nèi)容”的格式,并以換行符作分隔。(windows里txt文檔在記事本等的默認換行為\r\n,即回車符+換行符,但是有些文本編輯器為適應(yīng)linux系統(tǒng)也支持\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(@"\[職業(yè)\](?<profession>.*)(\r\n){0,}?");
????????strs[2]?=?rex.Match(str).Groups["profession"].Value;
這里為了簡單演示使用streamreader讀取外部文件并用了string[]來儲存數(shù)據(jù)。實際上為了結(jié)構(gòu)的完善應(yīng)該定義一個用于保存內(nèi)容的class例如
public class player()
{
????????public string name;
????????public int level;
????????public string profession;
}
以便程序內(nèi)使用或者序列化之類的。
重點是正則表達式,在Regex?rex?=?new?Regex(@"\[名字\](?<name>.*)(\r\n){0,}?");中,形如@"\[名字\](?<name>.*)(\r\n){0,}?",這是使用了兩個比較重要的東西,捕獲命名組和惰性匹配。
捕獲命名組:(?<name>.*),將匹配式.*的匹配結(jié)果以字符串值的形式存到正則表達式匹配結(jié)果的groups中的["name"]內(nèi),在后面的rex.Match(str).Groups["name"].Value;中就可以取出這個匹配結(jié)果。
惰性匹配:(\r\n){0,}?"),匹配式\r\n將匹配0次以上,但盡量地少,這在不像C#這類使用分號;和反大括號}作為結(jié)尾的強結(jié)構(gòu)語言中具有重要意義(點名批評GDScript結(jié)構(gòu)層次不分明),否則因為沒有結(jié)尾符號導(dǎo)致匹配結(jié)果出現(xiàn)了偏差,我們作為開發(fā)者是要負責(zé)任的(陰險)。
這就是簡單的讀取外部文件了,但是如果要像某大型多人在線橫板清關(guān)網(wǎng)游的腳本文件那樣做到形如
[if]
[attack success]
1
[/if]
[then]
[target]
`enemy`????-1
[add absolute damage]
`all`????`%`????35
[/then]
的話,那就要多花功夫了。