比方說我們正在匹配FIND files where file2=29 AND file32="12" OR file623134="file23"
作爲解釋,我會一步步做到這一點。
很明顯,一個正則匹配字符串的正則表達式會匹配。
FIND files where file2=29 AND file32="12" OR file623134="file23"
首先讓我們決定想從中讀取...並讓他們accessable什麼位。
FIND (files) where file(2)=(29) AND file(32)=("12") OR file(623134)=("file23")
在這裏,我們堅持圍繞所有我們想要讀出位支架。這將這些位定義爲「捕獲組」。在C#中,我們可以給他們一些名字。我們稍後會做。
現在...讓我們推廣這個正則表達式,以便它匹配更多的例子..關鍵是數字,所以我們可以用[0-9]+
來捕獲它們。這意味着match a character in the range 0 to 9, at least once
。
FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("12") OR file([0-9]+)=("file23")
好了..現在的價值觀......這裏的一些都是字符串..讓匹配...
一個字符串的東西,是不是"
通過「包圍」的或"[^"]+"
(注..正意味着,我們需要至少一個角色,我們不能匹配空字符串。一個*
將讓你匹配空字符串。)
FIND (files) where file([0-9]+)=(29) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+")
一個在本例中的值是一個數..所以讓假定它們可以intergers。
FIND (files) where file([0-9]+)=([0-9]+) AND file([0-9]+)=("[^"]+") OR file([0-9]+)=("[^"]+")
沒有讓第一個例子特別..所以讓我們假設所有的值可以是字符串或整數。要做出兩個選擇,我們使用|
選項匹配器。 (現在..我想你在畫面上大喊「不,他們可以是任何東西......不只是字符串和數字」,但沒關係,我會處理的,後來過。)
FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) AND file([0-9]+)=("[^"]+"|[0-9]+) OR file([0-9]+)=("[^"]+"|[0-9]+)
現在...我們在這裏有一個相當重複的...最後的部分是相同的,除了一個有「或」,另一個有「與」。這是重要的..我們想知道什麼operator
正在使用...所以我們也捕獲。
FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+) (AND) file([0-9]+)=("[^"]+"|[0-9]+) (OR) file([0-9]+)=("[^"]+"|[0-9]+)
現在我們可以通過移除的最後一部分,並說這是以前的鍵/值對的重複係數進行重複。
FIND (files) where file([0-9]+)=("[^"]+"|[0-9]+)((AND|OR) file([0-9]+)=("[^"]+"|[0-9]+))*
我添加了一個「*」作爲表達的是最後一部分可以根據需要重複,或不存在一樣多次。
現在...如果我們想要處理的值是任何東西,浮動,時間等,我們需要包括每個匹配或一般的「任何」匹配器。兩者都有缺點。如果我們明確地匹配所有類型,我們就有更多的工作要做。如果我們不這樣做,那麼我們就需要對「如何知道價值何時完成?」做出一些假設。
假設我們假設值後有空格。然後我們就可以匹配所有的字符,直到我們打空白... [^\s]+
FIND (files) where file([0-9]+)=([^\s]+)((AND|OR) file([0-9]+)=([^\s]+))*
但現在..如果該值是一個字符串,並且它包含它打破的空白。 我們可能想單獨處理字符串來解決這個問題。
FIND (files) where file([0-9]+)=("[^"]+"|[^\s]+)((AND|OR) file([0-9]+)=("[^"]+"|[^\s]+))*
"[^"]+"
不處理你的字符串中的轉義字符。一個更好的匹配器是"(\\"|[^"])+"
其中說的是報價,然後反覆報價或不報價,然後報價。使用這將爲您的表達式添加一個新的捕獲組。我們並不需要這樣做,所以我們可以告訴它不要通過在括號內添加?:
來捕獲該組。例如"(?:\\"|[^"])+"
FIND (files) where file([0-9]+)=("(?:\\"|[^"])+"|[^\s]+)((AND|OR) file([0-9]+)=("(?:\\"|[^"])+"|[^\s]+))*
正如我提到的。在C#中,你可以命名捕捉組。您通過在組內添加?<name>
來完成此操作。
FIND (?<table>files) where file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+)((?<operator>AND|OR) file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+))*
該表達式中仍然存在重複..但是如果我們將它取出,我們將允許無效表達式匹配。例如。
FIND (?<table>files)((?<operator>AND|OR|where) file(?<key>[0-9]+)=(?<value>"(?:\\"|[^"])+"|[^\s]+))+
這將使FIND files AND file2="test"
匹配..這是不是真的要你想要的,但可能不夠好。
我可能只是使用字符串連接刪除重複,
var pair = @"(?<pair>file(?<key>[0-9]+)=(?<value>"(?:\\\"|[^\"])+\"|[^\s]+))";
var query = @"FIND (?<table>files) where "+pair+"((?<operator>AND|OR) "+pair+")*";
var ex = new Regex(query);
或只是把代碼檢查確保第一運營商「其中」
var query = @"FIND (?<table>files)(?<condition> (?<operator>AND|OR|where) file(?<key>[0-9]+)=(?<value>"(?:\\\"|[^\"])+\"|[^\s]+))+";
var ex = new Regex(query);
var match = ex.Match(...);
... match.Groups["table"].Value ...
你可以現在匹配一個字符串,循環雖然「條件」組,並要求他們的operator,
鍵, and
值`。
看到How do I access named capturing groups in a .NET Regex?
如果我理解你的權利,你想捕捉背後「文件」和值的數字。請試試這個:[Regex101](https://regex101.com/r/aH3wZ4/2) – benjamin
你想在C#或JavaScript中解決這個問題嗎? –
@ NigelThorne C#是首選,所以我可以在服務器端轉換它。但是如果有人在JavaScript中有解決方案,那麼它也是可以接受的。 –